我正在使用Twisted编写一个FTP客户端,可以下载大量文件,我正在尝试非常聪明地进行操作。但是,我一直遇到的问题是我会很快下载几个文件(有时候每批次约20个,有时约250个),然后下载会挂起,最后只有连接超时然后下载并挂起启动一遍又一遍。我正在使用DeferredSemaphore一次只下载3个文件,但我现在怀疑这可能不是避免限制服务器的正确方法。
以下是相关代码:
def downloadFiles(self, result, directory):
# make download directory if it doesn't already exist
if not os.path.exists(directory['filename']):
os.makedirs(directory['filename'])
log.msg("Downloading files in %r..." % directory['filename'])
files = filterFiles(None, self.fileListProtocol)
# from http://stackoverflow.com/questions/2861858/queue-remote-calls-to-a-python-twisted-perspective-broker/2862440#2862440
# use a DeferredSemaphore to limit the number of files downloaded simultaneously from the directory to 3
sem = DeferredSemaphore(3)
jobs = [sem.run(self.downloadFile, f, directory) for f in files]
d = gatherResults(jobs)
return d
def downloadFile(self, f, directory):
filename = os.path.join(directory['filename'], f['filename']).encode('ascii')
log.msg('Downloading %r...' % filename)
d = self.ftpClient.retrieveFile(filename, FTPFile(filename))
return d
您会注意到我正在重用FTP连接(顺便主动)并使用我自己的FTPFile实例来确保当文件下载连接“丢失”(即已完成)时本地文件对象被关闭。看FTPClient我想知道我是否应该直接使用queueCommand。说实话,我在retrieveFile命令_openDataConnection之后丢失了,所以也许它已经被使用了。
有什么建议吗?谢谢!
答案 0 :(得分:1)
我建议使用queueCommand,因为你建议我怀疑你使用的信号量可能会导致你的问题。我相信使用queueCommand会将你的FTPClient限制为单个活动连接(虽然我只是推测),所以如果你想快速做事,你可能想要创建一些FTPClient实例并将下载作业传递给它们。如果您使用queueStringCommand,则可以使用Deferred来确定每个客户端的位置,甚至可以在回调中为该客户端的队列添加另一个作业。