11

我想用 python ftplib 发送一个文件,从一个 ftp 站点到另一个,以避免文件读/写进程。

我创建了一个 BytesIO 流:

myfile=BytesIO()

我使用 retrbinary 从 ftp 站点一成功检索了图像文件:

ftp_one.retrbinary('RETR P1090080.JPG', myfile.write)

我可以将此内存对象保存到常规文件中:

fot=open('casab.jpg', 'wb')

fot=myfile.readvalue()

但是我无法通过带有 storbinary 的 ftp 发送这个流。我认为这会起作用:

ftp_two.storbinary('STOR magnafoto.jpg', myfile.getvalue())

但没有。我收到一个以 'buf = fp.read(blocksize) AttributeError: 'str' object has no attribute 'read' 结尾的长错误消息

我也尝试了许多荒谬的组合,但没有成功。顺便说一句,我也对我在 myfoto.write 上所做的真正感到困惑。不应该是 myfoto.write() 吗?

我对这个缓冲区的作用或需要什么也一无所知。我想要实现的目标太复杂了吗?我应该只在系统中使用中间写入/读取来 ping pong 文件吗?全部

编辑:感谢 abanert,我把事情搞清楚了。作为记录, storbinary 参数是错误的,并且需要一个 myfile.seek(0) 在发送之前“倒回”流。这是一个工作片段,可在两个 ftp 地址之间移动文件,而无需中间物理文件写入:

import ftplib as ftp
from io import BytesIO

ftp_one=ftp.FTP(address1, user1, pass1)
ftp_two=ftp.FTP(address2, user2, pass2)
myfile=BytesIO()
ftp_one.retrbinary ('RETR imageoldname.jpg', myfile.write)
myfile.seek(0)
ftp_two.storbinary('STOR imagenewname.jpg', myfile)
ftp_one.close()
ftp_two.close()
myfile.close()
4

1 回答 1

11

问题是您正在调用getvalue(). 只是不要这样做:

ftp_two.storbinary('STOR magnafoto.jpg', myfile)

storbinary需要一个可以调用的类文件对象read

幸运的是,您只有这样一个对象myfile, a BytesIO。(从您的代码中并不能完全清楚这里的事情顺序 - 如果这不能按原样工作,您可能需要myfile.seek(0)或以不同的模式或其他方式创建它。但是除非您做错了什么,否则 aBytesIO可以使用storbinary.)

但不是通过myfile,而是通过myfile.getvalue()。和getvalue“返回bytes包含缓冲区的全部内容”。

所以,不是给它一个storbinary可以调用的类文件对象,而是read给它一个bytes对象,这当然和strPython 2.x 中的一样,你不能调用read它。


在你身边:

顺便说一句,我也对我在 myfoto.write 上所做的真正感到困惑。不应该是 myfoto.write() 吗?

查看文档。第二个参数不是文件,它是一个回调函数。

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

您想要的是一个将每个数据块附加到myfoto. 虽然您可以编写自己的函数来做到这一点:

def callback(block_of_data):
    myfoto.write(block_of_data)

……很明显,这个函数和myfoto.write方法做的事情完全一样。因此,您可以只传递该方法本身。

如果您不了解绑定方法,请参阅教程中的方法对象


这种灵活性,虽然看起来很奇怪,但它让您做的事情甚至比将整个文件下载到缓冲区中以发送到另一台服务器更好。实际上,您可以同时打开两个连接,并使用回调将每个缓冲区从源服务器发送到目标服务器,而无需存储超过一个缓冲区。

但是,除非您真的需要,否则您可能不想经历所有这些复杂性。

其实,总的来说,ftplib是种低级的。storbinary它有一些设计(比如接受一个文件,同时接受一个回调的事实retrbinary)在低级别完全有意义,但从更高级别看起来很奇怪。因此,您可能希望通过在 PyPI 上进行搜索来查看一些更高级别的库。

于 2013-06-07T19:47:58.757 回答