0
Python的完整noob,但我已經做了簡單的FTP下載和上傳,寫入塊的磁盤,而不是寫入整個文件之前填充RAM塊。如何使用ftplib Python 2.7執行多段FTP下載?
我的問題是,如何立即將它寫入磁盤而不是先填充RAM,同時下載x部分文件(多個線程下載單個文件的不同部分)?
我已經找過這個例子,但他們先填充RAM然後寫出文件。
此外,我想知道是否有可能做到這一點上傳?
感謝
Python的完整noob,但我已經做了簡單的FTP下載和上傳,寫入塊的磁盤,而不是寫入整個文件之前填充RAM塊。如何使用ftplib Python 2.7執行多段FTP下載?
我的問題是,如何立即將它寫入磁盤而不是先填充RAM,同時下載x部分文件(多個線程下載單個文件的不同部分)?
我已經找過這個例子,但他們先填充RAM然後寫出文件。
此外,我想知道是否有可能做到這一點上傳?
感謝
所以我想通了自己:)
from ftplib import *
from threading import *
from shutil import *
import os
num_parts = 20
FTP_server = 'ftp.example.com'
FTP_user = 'mark'
FTP_password = 'password'
FTP_directory = '/foo/bar'
FTP_file = 'foo.bar'
class Done(Exception):
pass
def open_ftp():
ftp = FTP(FTP_server, FTP_user, FTP_password)
ftp.cwd(FTP_directory)
return ftp
def go():
ftp = open_ftp()
filesize = ftp.size(FTP_file)
print 'filesize: ' + str(filesize)
ftp.quit()
chunk_size = filesize/num_parts
last_chunk_size = filesize - (chunk_size * (num_parts - 1))
downloaders = []
for i in range(num_parts):
if i == (num_parts - 1):
this_chunk_size = last_chunk_size
else:
this_chunk_size = chunk_size
downloaders.append(Downloader(i, chunk_size * i, this_chunk_size))
for downloader in downloaders:
downloader.thread.join()
with open(FTP_file, 'w+b') as f:
for downloader in downloaders:
copyfileobj(open(downloader.part_name, 'rb'), f)
class Downloader:
thread_number = 0
def __init__(self, part_number, part_start, part_size):
self.filename = FTP_file
self.part_number = part_number
self.part_name = 'part' + str(self.part_number)
self.part_start = part_start
self.part_size = part_size
Downloader.thread_number += 1
self.thread_number = Downloader.thread_number
self.ftp = open_ftp()
self.thread = Thread(target=self.receive_thread)
self.thread.start()
def receive_thread(self):
try:
self.ftp.retrbinary('RETR '+self.filename, self.on_data, 100000, self.part_start)
except Done:
pass
def on_data(self, data):
with open(self.part_name, 'a+b') as f:
f.write(data)
if os.path.getsize(self.part_name) >= self.part_size:
with open(self.part_name, 'r+b') as f:
f.truncate(self.part_size)
raise Done
go()
所以我據悉,從retrbinary回調是,它得到實際的二進制數據。因此,對於每個線程,我創建一個文件並將該回調中的二進制數據附加到該文件中,直到文件的大小大於預期的大小,然後我們截斷額外的文件。 當所有線程完成時,文件將被連接起來,並生成一個具有原始文件名的文件。文件大小和sha256完成並確認它的工作原理。 :)
代碼改編自RichieHindle
對於大文件我看到下面的錯誤 文件「/python/2.7.3/lib/python2.7/ftplib.py」,線路555,在大小 resp = self.sendcmd('SIZE'+文件名) 文件「/python/2.7.3/lib/python2.7/ftplib.py」,第244行,在sendcmd中 return self.getresp() File「 /python/2.7.3/lib/python2.7/ftplib.py「,第219行,在getresp raise error_perm,resp ftplib.error_perm:550 foo.tgz:對於A型SIZE太大。 我該如何解決這個問題? ftp.sendcmd('binary')不起作用 – ghostkadost
@gostkadost引發的錯誤是使用權限(550),確保你給它正確的路徑。 –