从FTP下载文件时出现多进程错误

1 投票
1 回答
949 浏览
提问于 2025-04-18 11:16

我在这段代码上卡了很久,搞不清楚为什么它不工作。当我运行下面的代码时,总是会出现一个“pickling error”(序列化错误),而且每次出错的文件都不一样。

这段代码会下载随机数量的文件,然后就神奇地停止了。奇怪的是,第i个文件的名字(或者说它选择停止的地方)突然变得不能被序列化,而之前的文件都可以。我觉得要么它们都不能被序列化,要么都可以,但中间有几个不能被序列化就太奇怪了。

n=10
urls = ["ftp://ftp.sec.gov/{0:s}".format(f) for f in flist[:n]]
print urls
from multiprocessing import Pool
from urllib import urlretrieve

def download(url):
    try:
        file_name = str(url.split('/')[-1])
        print file_name
        return urlretrieve(url, file_name), None
    except Exception as e:
        return None, e

if __name__ == "__main__":
   p = Pool(10) 
   p.map(download, urls) 

我遇到的错误是:

Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
  File "/usr/local/lib64/anaconda/lib/python2.7/multiprocessing/pool.py", line 250, in map
    return self.map_async(func, iterable, chunksize).get()
  File "/usr/local/lib64/anaconda/lib/python2.7/multiprocessing/pool.py", line 554, in get
    raise self._value
multiprocessing.pool.MaybeEncodingError: Error sending result: '[(('0000950144-94-000788.txt', <mimetools.Message instance at 0x6333878>), None)]'. Reason: 'PicklingError("Can't pickle <type 'cStringIO.StringI'>: attribute lookup cStringIO.StringI failed",)'

有没有人知道为什么第i个元素突然不能被序列化了?而之前的那些文件却可以?我看到它认为第i个名字是一个stringIO(字符串输入输出),但这没道理,因为之前的那些也应该是这样才对。

1 个回答

1

你正在返回一个 mimetools.Message 对象,这个对象代表了FTP的头信息。你要么直接把它去掉,要么在返回之前把它转换成普通的字符串。

下面是后者的一个例子:

n=10
urls = ["ftp://ftp.sec.gov/{0:s}".format(f) for f in flist[:n]]
print urls
from multiprocessing import Pool
from urllib import urlretrieve

def download(url):
    try:
        file_name = str(url.split('/')[-1])
        print file_name
        filename,headers = urlretrieve(url, file_name)
        return (filename, repr(headers), None
    except Exception as e:
        return None, e

if __name__ == "__main__":
   p = Pool(10) 
   p.map(download, urls) 

撰写回答