[英]How to close file objects when downloading files over FTP using Twisted?
我有以下代码:
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。 为什么在下载每个文件后都应关闭它们时为什么? 如果还有一种更惯用的方式来完成下载大量文件的整个任务,我也很乐意听到。 谢谢。
更新: Jean-Paul的DeferredSemaphore
示例加上Matt的FTPFile
了目的。 由于某种原因,使用Cooperator
而不是DeferredSemaphore
会下载一些文件,然后失败,因为FTP连接将终止。
您要同时打开fileListProtocol.files
每个文件,将内容下载到它们,然后在每次下载完成后关闭每个文件。 因此,您将在该过程开始时打开len(fileListProtocol.files)
文件。 如果该列表中的文件太多,则您将尝试打开太多文件。
您可能想一次限制自己只有很少数量的并行下载(如果FTP甚至支持并行下载,我不确定是这种情况)。
http://jcalderone.livejournal.com/24285.html并将“ Python Twisted”透视图代理的远程调用排队? 可能有助于弄清如何限制并行开始的下载数量。
假设您使用的是来自twisted.protocols.ftp
...的FTPClient
,那么在与JP冲突之前我肯定会犹豫。
似乎您传递给retrieveFile
的FileConsumer
类将通过twisted.internet.protocol.ConsumerToProtocolAdapter
适应IProtocol
, twisted.internet.protocol.ConsumerToProtocolAdapter
不会调用unregisterProducer
,因此FileConsumer
不会关闭文件对象。
我已经敲定了一个可以用来接收文件的快速协议。 我认为只应在适当的时候打开文件。 完全未经测试,您可以在上面的代码中使用它代替FileConsumer
,并且不需要addCallback
。
from twisted.python import log
from twisted.internet import interfaces
from zope.interface import implements
class FTPFile(object):
"""
A consumer for FTP input that writes data to a file.
@ivar filename: a filename to be opened for writing.
"""
implements(interfaces.IProtocol)
def __init__(self, filename):
self.fObj = None
self.filename = filename
def makeConnection(self,transport)
self.fObj = open(self.filename,'wb')
log.info('Opened %s for writing' % self.filename)
def connectionLost(self,reason):
self.fObj.close()
log.info('Closed %s' % self.filename)
def dataReceived(self, bytes):
self.fObj.write(bytes)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.