0

私は次のコードを持っています:

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 接続が切断されて失敗します。

4

2 に答える 2

1

すべてのファイルをfileListProtocol.files同時に開き、コンテンツをダウンロードし、ダウンロードが完了するたびにそれぞれを閉じます。したがって、len(fileListProtocol.files)プロセスの開始時にファイルが開いています。そのリストにあまりにも多くのファイルがある場合は、あまりにも多くのファイルを開こうとします。

おそらく、一度に実行できる並列ダウンロードの数をかなり少数に制限したいと思うでしょう (もし FTP が並列ダウンロードをサポートしているとしても、それが正しいかどうかは完全にはわかりません)。

http://jcalderone.livejournal.com/24285.htmlおよびPython Twisted パースペクティブ ブローカーへのキュー リモート呼び出し? 並行して開始するダウンロードの数を制限する方法を理解するのに役立つかもしれません.

于 2010-08-10T15:00:16.457 に答える
1

FTPClientfrom ...を使用していると仮定すると、twisted.protocols.ftpJP と矛盾する前に確かに躊躇します..

FileConsumerあなたが渡しているクラスは、を呼び出さないによってretrieveFile適応されるようです。そのため、ファイル オブジェクトを閉じません。IProtocoltwisted.internet.protocol.ConsumerToProtocolAdapterunregisterProducerFileConsumer

ファイルを受信するために使用できる簡単なプロトコルを作成しました。適切な場合にのみファイルを開く必要があると思います。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)
于 2010-08-10T15:32:02.613 に答える