我希望用python从一个ftp站点发送一个文件到另一个ftp站点,以避免文件读/写过程。
我创建一个BytesIO流:
myfile=BytesIO()
我成功地从ftp站点检索了一个图像文件,其中一个文件带有retrbinary:
ftp_one.retrbinary('RETR P1090080.JPG', myfile.write)
我可以将这个内存对象保存到一个常规文件中:
fot=open('casab.jpg', 'wb')
fot=myfile.readvalue()
但我无法通过ftp发送此流,并使用storbinary。我以为这会成功的:
ftp_two.storbinary('STOR magnafoto.jpg', myfile.getvalue())
但事实并非如此。我得到了一个长错误消息,结尾为'buf =fp.read(块大小) AttributeError:'str‘对象没有属性'read’
我也尝试过许多荒谬的组合,但都没有成功。顺便说一句,我也很困惑我到底在用myfoto.write做什么。是不是应该是myfoto.write()?
我也完全不知道这个缓冲设备做什么或需要什么。我想要的东西太复杂了吗?我应该只是在我的系统中用中间写/读的文件打乒乓球吗?泰尔
编辑:多亏了阿班纳特,我把事情搞清楚了。为了记录在案,存储二进制参数是错误的,在发送流之前需要一个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()
发布于 2013-06-07 19:47:58
问题是你要打电话给getvalue()
。别这么做:
ftp_two.storbinary('STOR magnafoto.jpg', myfile)
storbinary
需要一个可以调用read
的类似文件的对象。
幸运的是,您有这样一个对象,myfile
,一个BytesIO
。(从您的代码中还不完全清楚这里的顺序是什么--如果这不能按原样工作,您可能需要以不同的模式或其他方式创建它。但是,除非您做错了什么,否则BytesIO
将与storbinary
一起工作。)
但不是传递myfile
,而是传递myfile.getvalue()
。和getvalue
“返回包含缓冲区全部内容的bytes
。
因此,您不是为storbinary
提供一个可以调用read
的类似文件的对象,而是给它一个bytes
对象,这当然与Python2.x中的str
相同,而且您不能在此上调用read
。
为了你的旁白:
顺便说一句,我也很困惑我到底在用myfoto.write做什么。是不是应该是myfoto.write()?
看看医生们。第二个参数不是文件,而是回调函数。
对接收到的每个数据块调用回调函数,其中一个字符串参数给出数据块。
您需要的是将每个数据块附加到myfoto
末尾的函数。虽然您可以编写自己的函数来实现这一点:
def callback(block_of_data):
myfoto.write(block_of_data)
…很明显,这个函数与myfoto.write
方法执行的任务完全相同。因此,您只需传递该方法本身。
如果您不了解绑定方法,请参阅本教程中的方法对象。
这种灵活性看起来很奇怪,它允许您做一些比将整个文件下载到缓冲区发送到另一台服务器更好的事情。实际上,您可以同时打开这两个连接,并使用回调将每个缓冲区从源服务器发送到接收到的目标服务器,而不需要存储多个缓冲区。
但是,除非你真的需要,否则你可能不想经历那么复杂的事情。
事实上,总的来说,ftplib
是低水平的.而且它有一些设计(比如storbinary
接受一个文件,而retrbinary
接受一个回调),这些设计在那么低的级别上是完全有意义的,但从更高的层次上看似乎很奇怪。因此,您可能需要通过执行一个在PyPI搜索来查看一些较高级别的库。
https://stackoverflow.com/questions/16991819
复制相似问题