枚举循环中的多处理

Multiprocessing in enumerate loop

我有一个从 url 下载图像的脚本,但我想将它并行化,否则会花费数小时。使用此代码:

import requests
from math import floor, log10
import urllib 
import time
import multiprocessing

with open('images.csv', 'r') as f:
    images = f.readlines()

num_position = floor(log10(len(images)) + 1)

a = time.time()

for i, image in enumerate(images[1:10]):
    if (i+1) % 1000 == 0:
        print('Downloading {} image'.format(i+1) )
#   a = time.time()
    with open(str(i).zfill(num_position)+'a.jpg', 'wb') as file:
        try:
            writing = file.write(requests.get(image.split(',')[2]).content)
            p = multiprocessing.Process(target=writing, args=(image,))  
            p.start()
            p.join()    
        except:
            print('Skipping an image!')
            pass
b = time.time()
print('multiple process -- {}'.format(b-a)) 

我收到一个错误:

    Process Process-9:
Traceback (most recent call last):
  File "/usr/lib/python3.4/multiprocessing/process.py", line 254, in _bootstrap
    self.run()
  File "/usr/lib/python3.4/multiprocessing/process.py", line 93, in run
    self._target(*self._args, **self._kwargs)
TypeError: 'int' object is not callable
  1. 为什么我收到错误但任务仍然完成并且代码没有中断? (我指的是尝试中的作品:)
  2. 在这里包含某种并行的最简单方法是什么?

你得到这个错误是因为 AFAIK 这一行

writing = file.write(requests.get(image.split(',')[2]).content)

有整数类型的输出。 write returns 写入的字符数等于图像字符串表示的长度。现在你把它分配给变量 writing -> writing 变成一个数字。

p = multiprocessing.Process(target=writing, args=(image,))

调用 writing 作为目标函数,这会引发错误,因为您调用的不是函数而是整数类型 writing(不可调用)。该代码有效,因为您的工作人员没有任何事情要做并立即关闭并且文件已经写入。

为了让事情正常进行,您必须定义一个函数,将您的图像作为参数,也许还有文件名。您稍后会在您的工作人员的设置中调用此功能。类似的东西:

def write_file(image, filename):
    filestream = open(filename, mode="w")
    filestream.write(requests.get(image.split(',')[2]).content)
    filestream.close()

并且在您的申请中

p = multiprocessing.Process(target=write_file, args=(image, filename,)) 

然而,这只是写作部分。如果您也想在单独的任务中进行下载,那么您必须将相关代码放入单独的函数中。

def download_write(urls):
    for url in iter(urls.get, 'STOP'):
        #download code here#
        filestream = open(filename, mode="w")
        filestream.write(requests.get(image.split(',')[2]).content)
        filestream.close()

您的主要应用程序:

list_urls = [] # your list of urls to download
urls = Queue()
for element in list_urls:
    urls.put(element)
p = multiprocessing.Process(target=download_write, args=(urls,))
urls.put("STOP") #signals end of tasks for your workers
p.start() #start worker
p.join() #wait for worker to finish