ftp发送python字节流

ftp发送python字节流,python,file,memory,ftplib,bytesio,Python,File,Memory,Ftplib,Bytesio,我想用python ftplib将一个文件从一个ftp站点发送到另一个ftp站点,以避免文件读/写过程 我创建一个字节流: myfile=BytesIO() 我用retrbinary成功地从ftp站点1检索到一个图像文件: ftp_one.retrbinary('RETR P1090080.JPG', myfile.write) 我可以将此内存对象保存到常规文件: fot=open('casab.jpg', 'wb') fot=myfile.readvalue() 但是我不能用storb

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

我创建一个字节流:

myfile=BytesIO()
我用retrbinary成功地从ftp站点1检索到一个图像文件:

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”对象没有属性“read”

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

我也不知道这个缓冲的东西做什么或需要什么。我想要的东西太复杂而无法实现吗?我应该在我的系统中用中间写/读来乒乓这些文件吗?泰尔

编辑:多亏了阿巴纳特,我把事情搞清楚了。对于记录,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()

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

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

需要一个类似文件的对象,它可以调用
read

幸运的是,您有这样一个对象,
myfile
,一个。(从您的代码中还不完全清楚这里的事情顺序,如果它不能正常工作,您可能需要
myfile.seek(0)
或以其他模式或其他方式创建它。但是
BytesIO
将与
storbinary
一起工作,除非您做错了什么。)

但不是传递
myfile
,而是传递
myfile.getvalue()
。和“返回包含缓冲区全部内容的
字节
。”

因此,与其给
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
接受一个回调),这些设计在低级别上完全有意义,但从高级别上看似乎非常奇怪。因此,您可能希望通过执行一个.

来查看一些更高级的库。我这样做了,将myfile传递给storbinary。它确实创建了一个文件,但长度为0字节。@jose:好吧,如果你想调试它,你必须发布一个完整的示例,但最有可能的情况是我在回答中已经提到的:如果你创建了一个空的读写
BytesIO
,然后写入它,然后从它读取,你从最后读取,所以没有什么可读取的。您可以通过从可写的
BytesIO
缓冲区中创建一个新的可读
BytesIO
来解决这个问题,或者只需在其上调用
seek(0)
。是的,这是有意义的。我明天再查。玩弄文件流而没有正确研究它们是我的错。我不知道这些流有读取位置。感谢你的帮助,玩弄它们是一个很好的学习方式。也许可以尝试在交互式解释器中玩弄小程序,在那里你可以直接看到每一步发生了什么,而不是试图根据大型程序与服务器交互的效果进行猜测。但总的来说,不要放弃通过实验学习!好的,试过了,一个简单的myfile.seek(0)让一切正常。谢谢,abanert,我将编辑主要帖子以保存到未来。我确实在空闲时玩弄工具,但有两个障碍(误读storbinary中的参数和忽略“回放”数据流的需要),我完全迷路了。旁注:“我可以将此内存对象保存到常规文件”实际上根本不保存信息
fot=open('casab.jpg','wb')
创建一个新的空文件,然后
fot=myfile.readvalue()
忘记文件对象,将其替换为字符串。您需要类似于
fot.write(myfile.readvalue())
的东西来实际写入文件。(您可能需要也可能不需要先
myfile.seek(0)
)非常感谢您的提示,BytesIO流需要使用seek(0)进行“倒带”!这修复了我的问题,即上载成功,但文件为空\o/