在ftR

时间:2015-09-01 19:38:41

标签: python ftp

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

在实际案例场景中,我需要获得preios修改时间,存储在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()

1 个答案:

答案 0 :(得分:2)

根据retrbinary的文件:

  

每个接收的数据块调用回调函数,其中一个字符串参数给出数据块。

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

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数据。