【问题标题】:Python ftplib cannot use STOR in callback function following RETRPython ftplib 不能在 RETR 后的回调函数中使用 STOR
【发布时间】:2015-09-02 04:12:04
【问题描述】:

这是我需要完成的任务: - 连接到 FTP - 获取 test.txt 的内容 - 得到结果后立即将新内容写入test.txt

在实际情况下,我需要获取 previos 修改时间,存储在 txt 文件中,然后仅将那些在该时间之后修改的文件上传到 FTP,而不专门检查每个文件(有数千个,那将是太长了)。

这就是我卡住的地方。

def continueTest(data, ftp):
    print(data, ftp)
    with open('test.txt', 'w+') as file:
        file.write('test')
    with open('test.txt', 'rb') as file:
        ftp.storbinary('STOR htdocs/test.txt', file)

def test():
    host_data=FTP_HOSTS['planz-norwegian']
    ftp = ftplib.FTP(host=host_data['server'],
                     user = host_data['username'],
                     passwd = host_data['password'])
    print('connected to ftp')
    ftp.retrbinary('RETR htdocs/test.txt', lambda data:continueTest(data, ftp))


if __name__=='__main__':
    test()

这个输出:

connected to ftp
b'test' <ftplib.FTP object at 0x0322FAB0>
Traceback (most recent call last):
  File "C:\Python33\Plan Z Editor SL\redistdb.py", line 111, in <module>
    test()
  File "C:\Python33\Plan Z Editor SL\redistdb.py", line 107, in test
    ftp.retrbinary('RETR htdocs/test.txt', lambda data:continueTest(data, ftp))
  File "C:\Python33\lib\ftplib.py", line 434, in retrbinary
    callback(data)
  File "C:\Python33\Plan Z Editor SL\redistdb.py", line 107, in <lambda>
    ftp.retrbinary('RETR htdocs/test.txt', lambda data:continueTest(data, ftp))
  File "C:\Python33\Plan Z Editor SL\redistdb.py", line 99, in continueTest
    ftp.storbinary('STOR htdocs/test.txt', file)
  File "C:\Python33\lib\ftplib.py", line 483, in storbinary
    with self.transfercmd(cmd, rest) as conn:
  File "C:\Python33\lib\ftplib.py", line 391, in transfercmd
    return self.ntransfercmd(cmd, rest)[0]
  File "C:\Python33\lib\ftplib.py", line 351, in ntransfercmd
    host, port = self.makepasv()
  File "C:\Python33\lib\ftplib.py", line 329, in makepasv
    host, port = parse227(self.sendcmd('PASV'))
  File "C:\Python33\lib\ftplib.py", line 873, in parse227
    raise error_reply(resp)
ftplib.error_reply: 200 Type set to I.

如果我不在回调中使用 STOR,一切正常,但是,我应该如何从 RETR 命令获取数据? 我知道可能的解决方案,但我确信一定有一个更优雅的解决方案: - 使用 urllib.request 而不是 RETR(如果服务器上没有 HTTP 怎么办?) - 在回调函数中重新初始化 FTP 连接(由于等待服务器重新连接,可能比预期慢) - 用户ftp.set_pasv(False)(回调启动,但脚本没有结束,不能使用ftp.quit()ftp.close()

【问题讨论】:

    标签: python ftp


    【解决方案1】:

    根据retrbinary的文档:

    回调函数为接收到的每个数据块调用,单个字符串参数给出数据块。

    这表明在检索文件的数据连接仍处于打开状态且 STOR 命令尚未完成时调用回调。 FTP 无法在另一个仍处于活动状态时创建新的数据连接(在同一个 FTP 会话中)。此外,ftplib 看起来很困惑,并认为对 TYPE I 的响应是对 PASV 的响应:

    File "C:\Python33\lib\ftplib.py", line 873, in parse227
        raise error_reply(resp)
    ftplib.error_reply: 200 Type set to I.
    

    您应该做的是仅在 RETR 完成后调用 STOR,即让回调将所有内容存储在文件中,但只有在 retrbinary 返回后才打开文件。

    但是,我应该如何从 RETR 命令获取数据?

    在您当前的回调中,您将数据存储在一个文件中,然后您读取该文件。回调仍应将数据存储在文件中,但读取和调用 STOR 应在回调之外完成,就在retrbinary 之后。您不能并行 RETR 和 STOR 数据。

    【讨论】:

    • 将接收到的数据存储在一个文件中很好,但是是否可以将其存储在一个变量中,至少是一个全局变量?它只是一个带时间的日期,这很难证明将文件系统作为缓冲区涉及到服务器是合理的。感谢您的回复!
    • @HelgaIliashenko:当然可以,但是由于您将内容存储在文件中,因此我认为这就是您想要的。示例代码见stackoverflow.com/questions/21783551/…
    猜你喜欢
    • 2011-01-01
    • 2016-05-16
    • 2012-01-07
    • 1970-01-01
    • 2019-05-03
    • 1970-01-01
    • 2019-06-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多