我知道 os.listdir,但据我所知,它将目录中的所有文件名放入内存,然后返回列表。我想要的是一种生成文件名、对其进行处理,然后生成下一个文件名的方法,而无需将它们全部读入内存。
有什么办法吗?我担心使用这种方法更改文件名、添加新文件和删除文件的情况。一些迭代器阻止您在迭代期间修改集合,主要是通过在开始时拍摄集合状态的快照,并在每次 move 操作时比较该状态。如果有一个能够从路径产生文件名的迭代器,如果有修改集合的文件系统更改(添加、删除、重命名迭代目录中的文件),它是否会引发错误?
在某些情况下可能会导致迭代器失败,这完全取决于迭代器如何维护状态。使用 S.Lotts 示例:
filea.txt
fileb.txt
filec.txt
迭代器生成 filea.txt。在 processing 期间,filea.txt 重命名为 filey.txt,fileb.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 os.scandir
正如我之前所写的那样,由于“iglob”只是一个真正的迭代器的外观,您必须调用低级系统函数才能像您想要的那样一次获得一个。幸运的是,可以从 Python 调用低级函数。 Windows 和 Posix/Linux 系统的底层函数不同。
win32api 是否有任何调用来读取“目录中的下一个条目”或如何继续。关于 C 函数的文档在这里: http://www.gnu.org/s/libc/manual/html_node/Opening-a-Directory.html#Opening-a-Directory
我提供了一段 Python 代码,演示了如何在我的系统 上调用低级 C 函数,但这段代码可能不适用于您的系统[footnote-1]。我建议打开你的 /usr/include/dirent.h 头文件并验证 Python 片段是否正确(你的 Python Structure 必须匹配 C struct) 在使用代码段之前。
这是使用 ctypes 和 libc 我放在一起的片段,它允许您获取每个文件名,并对其执行操作。请注意,当您对结构上定义的 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/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题