2013-06-07 25 views
5

Tôi muốn gửi tệp có ftplib python, từ một trang web ftp này đến trang khác, do đó, để tránh tệp đọc/ghi processees.ftp gửi luồng python byteio

tôi tạo ra một dòng BytesIO:

myfile=BytesIO() 

Và tôi thành công lấy một file ảnh từ ftp site một với retrbinary:

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

tôi có thể tiết kiệm đối tượng bộ nhớ này vào một tập tin thường xuyên:

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

fot=myfile.readvalue() 

Nhưng tôi không thể gửi luồng này qua ftp với storbinary. Tôi nghĩ điều này sẽ hoạt động:

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

Nhưng không. tôi nhận được một thông báo lỗi dài kết thúc bằng 'buf = fp.read (blockize) AttributeError: đối tượng' str 'không có thuộc tính' read '

Tôi cũng đã thử nhiều kết hợp vô lý, nhưng không thành công. Là một sang một bên, tôi cũng khá bối rối với những gì tôi đang thực sự làm với myfoto.write. Không nên là myfoto.write()?

Tôi cũng khá thất bại với những gì mà bộ đệm này làm hoặc yêu cầu. Là những gì tôi muốn quá phức tạp để đạt được? Tôi có nên ping pong các tập tin với một viết/đọc trung gian trong hệ thống của tôi? Ty tất cả

CHỈNH SỬA: cảm ơn tôi đã hiểu mọi thứ một cách thẳng thắn. Đối với hồ sơ, đối số storbinary đã sai và một myfile.seek (0) là cần thiết để 'tua lại' các dòng trước khi gửi nó. Đây là một đoạn làm việc mà di chuyển một tập tin giữa hai địa chỉ ftp mà không cần tập thể chất trung gian viết:

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() 
+0

Lưu ý phụ: "Tôi có thể lưu đối tượng bộ nhớ này vào một tệp thông thường" không thực sự lưu thông tin. 'fot = open ('casab.jpg', 'wb')' tạo một tệp trống mới, sau đó 'fot = myfile.readvalue()' quên về đối tượng tệp, thay thế nó bằng một chuỗi. Bạn cần một cái gì đó như 'fot.write (myfile.readvalue())' để thực sự ghi vào một tập tin. (Bạn có thể hoặc có thể không cần đến 'myfile.seek (0)' trước tiên.) – abarnert

Trả lời

3

Vấn đề là bạn đang gọi điện thoại getvalue(). Chỉ cần không làm điều đó:

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

storbinary đòi hỏi một đối tượng tập tin như vậy nó có thể gọi read trên.

May mắn thay, bạn chỉ có một đối tượng như vậy, myfile, một BytesIO. (Nó không hoàn toàn rõ ràng từ mã của bạn những gì chuỗi các sự vật là ở đây - nếu điều này không làm việc như-là, bạn có thể cần phải myfile.seek(0) hoặc tạo nó trong một chế độ khác nhau hoặc một cái gì đó.Nhưng một BytesIO sẽ làm việc với storbinary trừ khi bạn làm điều gì đó sai.)

Nhưng thay vì đi qua myfile, bạn vượt qua myfile.getvalue(). Và getvalue "Trả về bytes chứa toàn bộ nội dung của bộ đệm."

Vì vậy, thay vì đưa ra storbinary một đối tượng tập tin như vậy nó có thể gọi read trên, bạn đang đem lại cho nó một đối tượng bytes, đó là tất nhiên giống như str bằng Python 2.x, và bạn không thể hãy gọi read về điều đó.


Đối với một bên của bạn:

As an aside, I am also quite puzzled with what I am really doing with myfoto.write. Shouldnt it be myfoto.write() ?

Nhìn vào the docs. Tham số thứ hai không phải là một tệp, đó là hàm gọi lại.

The callback function is called for each block of data received, with a single string argument giving the data block.

Điều bạn muốn là chức năng nối từng khối dữ liệu vào cuối myfoto. Trong khi bạn có thể viết chức năng riêng của mình để làm điều đó:

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

... nó nên được khá rõ ràng rằng chức năng này thực hiện chính xác những điều tương tự như phương pháp myfoto.write. Vì vậy, bạn chỉ có thể vượt qua chính phương thức đó.

Nếu bạn không hiểu về phương pháp bị ràng buộc, hãy xem Method Objects trong hướng dẫn.


Tính linh hoạt này dường như tốt hơn là tải toàn bộ tệp xuống bộ đệm để gửi tới máy chủ khác. Bạn thực sự có thể mở hai kết nối cùng một lúc và sử dụng các cuộc gọi lại để gửi từng bộ đệm từ máy chủ nguồn đến máy chủ đích khi nó nhận được, mà không bao giờ lưu trữ bất kỳ thứ gì nhiều hơn một bộ đệm.

Nhưng, trừ khi bạn thực sự cần điều đó, bạn có thể không muốn trải qua tất cả sự phức tạp đó.

Thực tế, nói chung, ftplib là loại cấp thấp. Và nó có một số thiết kế (như thực tế là storbinary có một tập tin, trong khi retrbinary có một cuộc gọi lại) mà làm cho ý nghĩa tổng ở mức thấp nhưng có vẻ rất kỳ quặc từ một cấp độ cao hơn. Vì vậy, bạn có thể muốn xem một số thư viện cấp cao hơn bằng cách thực hiện một số search at PyPI.

+0

Tôi đã làm điều đó, thông qua myfile để storbinary. Nó tạo ra một tập tin, nhưng dài 0 byte. – jose

+0

@jose: Vâng, bạn sẽ phải đăng một ví dụ hoàn chỉnh nếu bạn muốn nó gỡ rối, nhưng khả năng nhất là một trong những tôi đã đề cập trong câu trả lời: Nếu bạn tạo một đọc trống ghi 'BytesIO', sau đó viết vào nó, sau đó đọc từ nó, bạn đang đọc từ cuối, vì vậy không có gì để đọc. Bạn có thể sửa lỗi đó bằng cách tạo ra một 'BytesIO' có thể đọc được từ bộ đệm' BytesIO' có thể ghi được, hoặc chỉ gọi 'seek (0)' trên nó. – abarnert

+0

có, điều này có ý nghĩa. Tôi sẽ kiểm tra vào ngày mai. Đó là lỗi của tôi để đồ chơi với các luồng tập tin mà không nghiên cứu chúng đúng cách. Tôi đã không có đầu mối những dòng này có một vị trí đọc. Ty cho sự giúp đỡ của bạn – jose