Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3-如何正确设置此多处理作业?_Python_Python 3.x_Parallel Processing_Multiprocessing - Fatal编程技术网

Python 3-如何正确设置此多处理作业?

Python 3-如何正确设置此多处理作业?,python,python-3.x,parallel-processing,multiprocessing,Python,Python 3.x,Parallel Processing,Multiprocessing,我有一个大约10000行的文件,每行代表下载作业的参数。我有5个自定义下载程序。每个作业可能需要5秒到2分钟的时间。如果下载程序当前不工作,如何创建遍历10000行的内容,将每个作业分配给下载程序 编辑: 对我来说,困难的部分是每个Downloader都是一个类的实例,而实例之间的差异是我在实例化5个Downloader对象时指定的端口号。所以我有a=Downloader(端口号=7751)。。。e=下载器(端口号=7755)。然后,如果我使用下载程序,我会执行a.run(row) 我如何将wo

我有一个大约10000行的文件,每行代表下载作业的参数。我有5个自定义下载程序。每个作业可能需要5秒到2分钟的时间。如果下载程序当前不工作,如何创建遍历10000行的内容,将每个作业分配给下载程序

编辑:

对我来说,困难的部分是每个
Downloader
都是一个类的实例,而实例之间的差异是我在实例化5个
Downloader
对象时指定的端口号。所以我有
a=Downloader(端口号=7751)。。。e=下载器(端口号=7755)
。然后,如果我使用
下载程序
,我会执行
a.run(row)


我如何将worker定义为这些
a、b、c、d、e
,而不是
下载函数

有很多方法可以做到这一点-最简单的方法就是使用
多处理。Pool
并让它为您组织worker-10k行并不多,假设一个平均URL的长度甚至是一个完整的KB,它仍然只需要10MB的内存,而且内存很便宜

因此,只需读取内存中的文件并将其映射到
multiprocessing.Pool
即可:

from multiprocessing import Pool

def downloader(param):  # our downloader process
    # download code here
    # param will hold a line from your file (including newline at the end, strip before use)
    # e.g. res = requests.get(param.strip())
    return True  # lets provide some response back

if __name__ == "__main__":  # important protection for cross-platform use

    with open("your_file.dat", "r") as f:  # open your file
        download_jobs = f.readlines()  # store each line in a list

    download_pool = Pool(processes=5)  # make our pool use 5 processes
    responses = download_pool.map(downloader, download_jobs)  # map our data, line by line
    download_pool.close()  # lets exit cleanly
    # you can check the responses for each line in the `responses` list
如果需要共享内存,您还可以使用
线程
而不是
多处理
(或
多处理.pool.ThreadPool
作为替代品)在单个进程内完成所有操作。一个线程对于下载来说已经足够了,除非你在做额外的处理

更新 如果希望下载程序作为类实例运行,可以将
downloader
函数转换为
downloader
实例的工厂,然后将实例化这些实例所需的内容与URL一起传递。下面是一个简单的循环方法:

from itertools import cycle
from multiprocessing import Pool

class Downloader(object):

    def __init__(self, port_number=8080):
        self.port_number = port_number

    def run(self, url):
        print("Downloading {} on port {}".format(url, self.port_number))

def init_downloader(params):  # our downloader initializator
    downloader = Downloader(**params[0])  # instantiate our downloader
    downloader.run(params[1])  # run our downloader
    return True  # you can provide your

if __name__ == "__main__":  # important protection for cross-platform use

    downloader_params = [  # Downloaders will be initialized using these params
        {"port_number": 7751},
        {"port_number": 7851},
        {"port_number": 7951}
    ]

    downloader_cycle = cycle(downloader_params)  # use cycle for round-robin distribution
    with open("your_file.dat", "r") as f:  # open your file
        # read our file line by line and attach downloader params to it
        download_jobs = [[next(downloader_cycle), row.strip()] for row in f]

    download_pool = Pool(processes=5)  # make our pool use 5 processes
    responses = download_pool.map(init_downloader, download_jobs)  # map our data
    download_pool.close()  # lets exit cleanly
    # you can check the responses for each line in the `responses` list
请记住,这并不是最平衡的解决方案,因为它可能恰好有两个
Downloader
实例运行相同的端口,但它将平均处理足够大的数据


如果要确保没有两个
Downloader
实例运行在同一个端口上,则需要构建自己的池,或者需要创建一个中心进程,在
Downloader
实例需要端口时向其发出端口。

将10000行读取到字符串列表中

with open('foo.dat') as f:
    data = f.readlines()
假设数据不包括端口号,并且编辑的问题提到5个端口,则应将其添加到数据中

data = [(p, d) for p, d in zip(itertools.cycle([7751, 7752, 7753, 7754, 7755]), data)]
编写一个函数,将其中一个元组作为参数,拆分它,创建一个Downloader对象并运行它

def worker(target):
    port, params = target
    d = Downloader(port_number=port)
    d.run(params)
    return params # for lack of more information.
使用
多处理.Pool
的方法,将您定义的函数和元组列表作为参数提供给它

imap\u unordered
返回的迭代器将在结果可用时立即开始生成结果。您可以打印它们以显示进度

p = multiprocessing.Pool()
for params in p.imap_unordered(worker, data):
    print('Finished downloading', params)
编辑


注意:如果您将要使用的
下载程序
对象的唯一方法是
run()
,那么它不应该是对象。这是一个伪装的功能!在Youtube上查找“停止编写类”视频并观看。

因此每个
下载程序都是一个类的实例,而实例之间的差异是在实例化5个
下载程序
对象时指定的
端口号。所以我有
a=Downloader(端口号=7751)。。。e=下载器(端口号=7755)
。然后,如果我使用
下载程序
,我会执行
a.run(row)
。你能建议一种方法将我的工作人员定义为这些
a、b、c、d、e
,而不是示例中的
downloader
函数吗?@user1367204-你应该在最初的问题中指定这一点。多处理类和预初始化类不是朋友(请检查)-问题是您的“Downloader”类将在主进程中实例化,当您生成新进程时,它将无权访问它。@user1367204-实例化这些“Downloader”类是一项昂贵的操作吗?i、 我们可以在开始下载时重新实例化一个新的吗(当然,仍然要考虑端口号)?在这种情况下,重新实例化没有问题。