我有以下代码:
for f in fileListProtocol.files:
if f['filetype'] == '-':
filename = os.path.join(directory['filename'], f['filename'])
print 'Downloading %s...' % (filename)
newFile = open(filename, 'w+')
d = ftpClient.retrieveFile(filename, FileConsumer(newFile))
d.addCallback(closeFile, newFile)
不幸的是,在下载了相关目录中的数百个1000多个文件后,我得到一个关于太多打开文件的IOError。为什么我应该在下载后关闭每个文件?如果有一种更惯用的方法来处理下载大量文件的整个任务,我很乐意听到它。感谢。
更新:让 - 保罗的DeferredSemaphore
示例加上马特的FTPFile
就行了。由于某些原因,使用Cooperator
而不是DeferredSemaphore
会下载一些文件然后失败,因为FTP连接已经死亡。
答案 0 :(得分:1)
您同时打开fileListProtocol.files
中的每个文件,将内容下载到它们,然后在每次下载完成时关闭每个文件。因此,您在流程开始时打开了len(fileListProtocol.files)
个文件。如果该列表中的文件太多,那么您将尝试打开太多文件。
您可能希望将自己限制在一些相当少量的并行下载中(如果FTP甚至支持并行下载,我不完全确定是这种情况)。
http://jcalderone.livejournal.com/24285.html和Queue remote calls to a Python Twisted perspective broker?可能有助于确定如何限制并行开始的下载次数。
答案 1 :(得分:1)
假设您使用的是来自FTPClient
的{{1}} ...而且在与JP发生冲突之前我当然犹豫不决..
您传递给twisted.protocols.ftp
的{{1}}课程似乎会被FileConsumer
调整为retrieveFile
,IProtocol
不会调用twisted.internet.protocol.ConsumerToProtocolAdapter
,所以unregisterProducer
不会关闭文件对象。
我已经敲了一个可以用来接收文件的快速协议。我认为它应该只在适当时打开文件。完全未经测试,您可以在上面的代码中使用它代替FileConsumer
,而不需要FileConsumer
。
addCallback