如果我没弄错的话,这类事情很容易用multiprocessing来完成。只需编写一个函数来上传一个文件
例如def upload_one(filename):
""" This function uploads one file.
Perhaps is a a wrapper to your Popen call? """
然后对文件列表使用mulitprocessing
^{pr2}$
你也可以使用chunksize,如果上传速度很快的话,它会让速度稍微加快一点。在
当然,如果您需要传递的信息不仅仅是文件名,一个非常简单的方法就是将文件列表变成元组列表,然后在函数中解压它们。在
警告
有些人可能会认为这是一种不好的做法,因为你实际上是在使用一个映射函数来处理副作用。。。在
编辑
我想你的问题是p.map(self.upload_files(f), self.files_to_upload)
我不熟悉python中的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的(不幸的)限制。您发送到周围的所有对象都必须是可pickle的。显然,您的实例方法(绑定到类实例的方法)是不可pickle的。一个解决方案是你可以把它变成一个常规函数。你可以这样做。在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()
希望你能成功。祝你好运!在