gpt4 book ai didi

python - 有没有一种方法可以有效地生成包含数百万个文件的目录中的每个文件?

转载 作者:太空狗 更新时间:2023-10-29 17:36:07 25 4
gpt4 key购买 nike

我知道 os.listdir,但据我所知,它将目录中的所有文件名放入内存,然后返回列表。我想要的是一种生成文件名、对其进行处理,然后生成下一个文件名的方法,而无需将它们全部读入内存。

有什么办法吗?我担心使用这种方法更改文件名、添加新文件和删除文件的情况。一些迭代器阻止您在迭代期间修改集合,主要是通过在开始时拍摄集合状态的快照,并在每次 move 操作时比较该状态。如果有一个能够从路径产生文件名的迭代器,如果有修改集合的文件系统更改(添加、删除、重命名迭代目录中的文件),它是否会引发错误?

在某些情况下可能会导致迭代器失败,这完全取决于迭代器如何维护状态。使用 S.Lotts 示例:

filea.txt
fileb.txt
filec.txt

迭代器生成 filea.txt。在 processing 期间,filea.txt 重命名为 filey.txtfileb.txt 重命名为 文件z.txt。当迭代器尝试获取下一个文件时,如果它使用文件名 filea.txt 找到它的当前位置以便找到下一个文件和 filea.txt不存在,会发生什么?它可能无法恢复它在集合中的位置。类似地,如果迭代器在生成 filea.txt 时要获取 fileb.txt,它可能会查找 fileb.txt 的位置,失败,并产生错误。

如果迭代器能够以某种方式维护索引 dir.get_file(0),那么维护位置状态将不会受到影响,但一些文件可能会丢失,因为它们的索引可能会被移动到迭代器“后面”的索引。

当然这都是理论上的,因为似乎没有内置(python)方法来迭代目录中的文件。但是,下面有一些很好的答案,它们通过使用队列和通知来解决问题。

编辑:

关注的操作系统是 Redhat。我的用例是这样的:

进程 A 不断地将文件写入存储位置。进程 B(我正在编写的进程)将迭代这些文件,根据文件名进行一些处理,并将文件移动到另一个位置。

编辑:

有效的定义:

形容词1. 有根据或有根据,中肯。

(对不起,S.Lott,我无法抗拒)。

我已经编辑了上面有问题的段落。

最佳答案

tl;dr : 从 Python 3.5(目前处于测试阶段)开始,只需使用 os.scandir

正如我之前所写的那样,由于“iglob”只是一个真正的迭代器的外观,您必须调用低级系统函数才能像您想要的那样一次获得一个。幸运的是,可以从 Python 调用低级函数。Windows 和 Posix/Linux 系统的底层函数不同。

  • 如果您使用的是 Windows,您应该检查 win32api 是否有任何调用来读取“目录中的下一个条目”或如何继续。
  • 如果您使用的是 Posix/Linux,则可以继续直接通过 ctypes 调用 libc 函数,并一次获取一个文件目录条目(包括命名信息)。

关于 C 函数的文档在这里: http://www.gnu.org/s/libc/manual/html_node/Opening-a-Directory.html#Opening-a-Directory

http://www.gnu.org/s/libc/manual/html_node/Reading_002fClosing-Directory.html#Reading_002fClosing-Directory

我提供了一段 Python 代码,演示了如何在我的系统 上调用低级 C 函数,但这段代码可能不适用于您的系统[footnote-1]。我建议打开你的 /usr/include/dirent.h 头文件并验证 Python 片段是否正确(你的 Python Structure 必须匹配 C struct) 在使用代码段之前。

这是使用 ctypeslibc 我放在一起的片段,它允许您获取每个文件名,并对其执行操作。请注意,当您对结构上定义的 char 数组执行 str(...) 时,ctypes 会自动为您提供一个 Python 字符串。 (我使用的是 print 语句,它隐式调用了 Python 的 str)

#!/usr/bin/env python2
from ctypes import *

libc = cdll.LoadLibrary( "libc.so.6")
dir_ = c_voidp( libc.opendir("/home/jsbueno"))

class Dirent(Structure):
_fields_ = [("d_ino", c_voidp),
("off_t", c_int64),
("d_reclen", c_ushort),
("d_type", c_ubyte),
("d_name", c_char * 2048)
]

while True:
p = libc.readdir64(dir_)
if not p:
break
entry = Dirent.from_address( p)
print entry.d_name

更新:Python 3.5 现在处于测试阶段 - 在 Python 3.5 中,新的 os.scandir 函数调用可作为 PEP 471 的具体化使用。 (“更好更快的目录迭代器”)它完全按照这里的要求进行操作,此外还有许多其他优化可以比 os.listdir 下的大型目录列表提供高达 9 倍的速度提升Windows(在 Posix 系统中增加 2-3 倍)。

[footnote-1] dirent64 C struct 是在每个系统的 C 编译时确定的。

关于python - 有没有一种方法可以有效地生成包含数百万个文件的目录中的每个文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5090418/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com