2012-05-07 4 views
1

그래서 많은 FTP 계정/서비스/무엇이든지간에 파일의 큰 서버 (디렉토리)를 백업하는 스크립트가 있습니다. 비서는이 작업을 수행하기 위해 복사하여 붙여 넣기하는 문서를 가지고 있지만, 어쨌든 나는 그 문서를 D에서 구할 수있는 작업 스크립트가있는 것 같습니다.파이썬 FTP 한번에 여러 파일 업로드

이전에는 스레딩이나 멀티 프로세싱과 관련하여 혼란스럽지 않았지만 파일 목록을 가져 와서 한 번에 호스트 3-5에 업로드하는 방법을 알 수는 없습니다. 이 예제에서는 5를 시도하고 있지만, 나는 무엇을 결정할 지 모르겠다.)

import os, sys, subprocess, shutil, re, string, glob, tvdb_api, itertools, multiprocessing, ftplib 

files = [os.path.join(r, f) for r, d, fs in os.walk(os.getcwd()) for f in fs if not f[0]=='.'] 
class FTP_Upload: 
    def __init__(self, p=os.getcwd()): 
     self.files_to_upload = sorted([f for f in files if os.path.split(f)[0] == p]) 
     self.target = raw_input("Enter the host you want to upload to: ") 
     self.host = FTP('ftp.host1.com', 'user_name1', 'super_secret_password1') if self.target == 'host' else FTP('ftp.host2.com', 'user_name2', 'secret_password2') if self.target == 'host2' else None 
    def upload_files(self, f): 
     self.host.storbinary(('STOR /'+f.split('/')[-1]), open(f, 'rb')) 
    def multiupload(self): 
     p = multiprocessing.Pool(processes=5) 
     p.map(self.upload_files(f), self.files_to_upload) 
FTP_Upload().multiupload() 

그러나 이것은 단지 self.files_to_upload의 마지막 파일을 업로드 ...

난 그냥 파일 목록 반복 가능

self.files_to_upload = iter(sorted([f for f in files if os.path.split(f)[0] == p])) 

그러나 기쁨을 만드는 시도했다.

미리 도움을 청하십시오!

+2

질문은 어디에 있습니까? 그리고 [ftplib] (http://docs.python.org/library/ftplib.html#module-ftplib)이 있다는 것을 알고 있습니까? – dav1d

+0

하하, 죄송합니다, 잠들지 않을 때 나는 더 많은 산책과 추가를합니다. 나는 키보드를 나 자신으로부터 멀리 가져 가야한다. 그러나 나는 그 똑똑한 사람이 아니다. –

답변

2

정확하게 이해하면 multiprocessing으로 쉽게 처리 할 수 ​​있습니다. 하나의 파일을 업로드하는 함수 작성 -

예 : 다음

def upload_one(filename): 
    """ This function uploads one file. 
     Perhaps is a a wrapper to your Popen call? """ 

당신은 또한 업로드가 빠른 경우 약간의 물건을 빠르게합니다 chunksize 영역 함께 놀러 수있는 파일

mylistoffiles=[ ] #Somehow generate your list of files to be uploaded. 
import multiprocessing 
Pool=multiprocessing.Pool(processes=X) #X is the number of processes you want to use 
Pool.map(upload_one,mylistoffiles) 

의 목록에 mulitprocessing 사용합니다.

물론 파일 이름보다 많은 정보를 전달해야하는 경우 파일 목록에 튜플 목록을 만들고 함수에서 파일의 압축을 푸는 것이 가장 쉬운 방법입니다.

당신은 본질적으로 부작용에 대한지도 기능을 사용하고 있기 때문에 일부는이 나쁜 관행을 고려해 볼 수 있습니다

경고 ...

내가 문제가 p.map(self.upload_files(f), self.files_to_upload) 생각

편집 파이썬에서 FTP에 익숙하지 않아 확실하게 말할 수는 없지만 함수 인을 전달하려고합니다. 첫 번째 매개 변수는 p.map입니다. 함수의 결과물을 전달 중입니다. 함수를 반환하는 함수를 작성할 수도 있지만 위 코드 에서처럼 보이지는 않습니다.

당신이 아마 원하는 것은 다음과 같이

일반적으로
p.map(self.upload_files,self.files_to_upload) 

가하는 map 함수에 대한 호출이 지능형리스트로 변환 할 수 있습니다

map(function,iterable) 

입니다

거의 동등한
[function(i) for i in iterable] 

(거의 동일합니다. python3.x에서 map은 발전기를 반환합니다. map에서 실제로 함수를 호출하지 않습니다.

최종 편집 (희망)

당신은 multiprocessing의 (불행한) 제한으로 실행 중입니다. 주위에 보내는 모든 물체는 pickleable이어야합니다. 분명히 인스턴스 메소드 (클래스 인스턴스에 바인드 된 메소드)는 피할 수 없습니다. 한 가지 해결책은 일반적인 기능으로 바꿀 수 있다는 것입니다. 다음과 같이 할 수 있습니다.

import os, sys, subprocess, shutil, re, string, glob, tvdb_api, itertools, multiprocessing, ftplib 

#No longer an instance method -- just a regular function. 
#accepts an iterable and then splits it as [host,filename] 
def upload_files(inpt): 
    host=inpt[0] 
    f=inpt[1] 
    #host,f=inpt #This might be a little cleaner, depending on your programming style. 
    host.storbinary(('STOR /'+f.split('/')[-1]), open(f, 'rb')) 

files = [os.path.join(r, f) for r, d, fs in os.walk(os.getcwd()) for f in fs if not f[0]=='.'] 
class FTP_Upload: 
    def __init__(self, p=os.getcwd()): 
     self.files_to_upload = sorted([f for f in files if os.path.split(f)[0] == p]) 
     self.target = raw_input("Enter the host you want to upload to: ") 
     self.host = FTP('ftp.host1.com', 'user_name1', 'super_secret_password1') if self.target == 'host' else FTP('ftp.host2.com', 'user_name2', 'secret_password2') if self.target == 'host2' else None 
    def multiupload(self): 
     p = multiprocessing.Pool(processes=5) 
     upload_this=[(self.host,f) for f in self.files_to_upload] 
     p.map(upload_files,upload_this) 
FTP_Upload().multiupload() 

잘하면 그게 잘 될거야. 행운을 빕니다!

+0

@RobinHood 위의 편집을 참조하십시오. 나는 당신이 거의 그것을 가지고 있다고 생각합니다. – mgilson

+0

고마워요,하지만 내가 multipupload에서 "(f)"를 제거했지만 지금은'가장 최근에 전화를 마지막 전화 :'023 :/"실행 자기 .__ 대상 (* 자기 .__ 인수, ** 자기 .__ kwargs로) 파일에 __bootstrap_inner self.run() 파일"/usr/lib/python2.7/threading.py ", 라인 (505)에 _handle_tasks에있는 315 행의 "/ usr/lib/python2.7/multiprocessing/pool.py" put (작업) PicklingError : 피클 링 > : 속성 조회 __builtin __. instancemethod failed –

+0

@RobinHood' 다시 편집했습니다. 추적 표시에서 알 수 있듯이 인스턴스 메소드를 피할 수는 없습니다. 그것을 정기적 인 기능으로 변경하면 모든 설정이 이루어지기를 바랍니다. – mgilson