如何在使用Twisted通过FTP下载文件时关闭文件对象?

时间:2010-08-10 14:15:31

标签: python ftp twisted ioerror

我有以下代码:

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连接已经死亡。

2 个答案:

答案 0 :(得分:1)

您同时打开fileListProtocol.files中的每个文件,将内容下载到它们,然后在每次下载完成时关闭每个文件。因此,您在流程开始时打开了len(fileListProtocol.files)个文件。如果该列表中的文件太多,那么您将尝试打开太多文件。

您可能希望将自己限制在一些相当少量的并行下载中(如果FTP甚至支持并行下载,我不完全确定是这种情况)。

http://jcalderone.livejournal.com/24285.htmlQueue remote calls to a Python Twisted perspective broker?可能有助于确定如何限制并行开始的下载次数。

答案 1 :(得分:1)

假设您使用的是来自FTPClient的{​​{1}} ...而且在与JP发生冲突之前我当然犹豫不决..

您传递给twisted.protocols.ftp的{​​{1}}课程似乎会被FileConsumer调整为retrieveFileIProtocol不会调用twisted.internet.protocol.ConsumerToProtocolAdapter,所以unregisterProducer不会关闭文件对象。

我已经敲了一个可以用来接收文件的快速协议。我认为它应该只在适当时打开文件。完全未经测试,您可以在上面的代码中使用它代替FileConsumer,而不需要FileConsumer

addCallback