- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
所以,我正在编写一个脚本,用于将大型服务器(目录)的文件备份到多个 FTP 帐户/服务/其他内容(目前可怜的秘书有一个副本--粘贴文档来执行此操作,但无论如何,我即将有一个工作脚本来将她从那个 =D)中拯救出来。
我之前并没有真正搞过线程或多处理,但我不知道如何让它获取文件列表并一次将它们全部上传到主机 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]))
但没有喜悦。
预先感谢您的帮助!
最佳答案
如果我理解正确的话,这种事情可以通过多处理
轻松完成。只需编写一个函数来上传一个文件 --
例如
def upload_one(filename):
""" This function uploads one file.
Perhaps is a a wrapper to your Popen call? """
然后对文件列表使用多重处理
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)
您还可以调整 block 大小,如果上传速度很快,这会加快速度。
当然,如果您需要传递文件名之外的更多信息,实现此目的的一种非常简单的方法是将文件列表设为元组列表,然后在函数中将它们解压。
警告
有些人可能会认为这种做法不好,因为您实际上是在使用 map 函数来产生副作用......
编辑
我认为你的问题是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
中您实际上并没有调用该函数。
最终编辑(希望如此)
您遇到了多处理
的(不幸的)限制。您发送的所有对象都必须是可腌制的。显然你的实例方法(绑定(bind)到类实例的方法)是不可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()
希望这对您有用。祝你好运!
关于Python FTP 一次上传多个文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10481747/
我有以下正则表达式 /[a-zA-Z0-9_-]/ 当字符串只包含从 a 到z 大小写、数字、_ 和 -。 我的代码有什么问题? 能否请您向我提供一个简短的解释和有关如何修复它的代码示例? //var
我是一名优秀的程序员,十分优秀!