Python 导入的包在并行计算期间无法识别?

Python 导入的包在并行计算期间无法识别?,python,python-3.x,parallel-processing,multiprocessing,multiprocess,Python,Python 3.x,Parallel Processing,Multiprocessing,Multiprocess,我正在使用multiprocess.Pool运行函数get_content in parallel setting。然后它抛出一个错误NameError:未定义名称“session”。显然,我用session=requests.session定义了它。你能详细说明一下这个问题吗 import requests, os from bs4 import BeautifulSoup from multiprocess import Pool, freeze_support core = os.cpu_

我正在使用multiprocess.Pool运行函数get_content in parallel setting。然后它抛出一个错误NameError:未定义名称“session”。显然,我用session=requests.session定义了它。你能详细说明一下这个问题吗

import requests, os
from bs4 import BeautifulSoup
from multiprocess import Pool, freeze_support
core = os.cpu_count()
session = requests.Session() 
headers = {'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0'}

links = ['https://www.investopedia.com/terms/1/0x-protocol.asp',
         'https://www.investopedia.com/terms/1/1-10net30.asp',
         'https://www.investopedia.com/terms/1/10-k.asp',
         'https://www.investopedia.com/terms/1/10k-wrap.asp',
         'https://www.investopedia.com/terms/1/10q.asp']

############ Get content of a word
def get_content(l):
    r = session.get(l, headers = headers)
    soup = BeautifulSoup(r.content, 'html.parser')
    entry_name = soup.select_one('#article-heading_3-0').contents[0]
    main = soup.select('.comp.article-body.mntl-block')[0]
    content = entry_name + '\n' + '<link href="investopedia.css" rel="stylesheet"/>' + '\n' + str(main) + '\n</>\n'
    return(content)

############ Parallel computing
if __name__=="__main__":
    P = Pool(processes = core)   
    content_list = P.map(get_content, links)
    content_all = ''.join(content_list)    
    freeze_support()

首先,您的进口声明不正确,应该是:

从多处理导入池中,冻结\u支持 你有来自多进程的…,所以我根本不知道它是如何运行的

使用正确的import语句,代码可以为我运行,但它并不是您所认为的那样!我从冻结支持的电话中推测,您正在Windows下运行。在该平台下,通过调用系统函数spawn来调用新的进程,这将导致整个程序从最顶层执行。这就是为什么创建新进程的代码必须位于由if _uname _uu=='_umain _u':'控制的块中。如果不是这样,那么您新创建的进程将重新执行刚刚在一个永无止境的递归循环中创建它们的代码,从而永远产生新的进程

这意味着由于以下语句处于全局范围,每个进程正在重新创建自己的会话实例:

会话=请求。会话 因此,对于您试图检索的多个URL,能够重复使用同一会话实例并没有带来任何实际好处。为了重用同一个会话实例,必须使用会话对象初始化多处理池本身,使其驻留在共享内存中并对所有进程可见。您还应该只在全局范围内保留最小的可执行代码:

导入请求,操作系统 从bs4导入BeautifulSoup 从多处理导入池中,冻结\u支持 headers={'User-Agent':'Mozilla/5.0 X11;Ubuntu;Linux x86_64;rv:78.0 Gecko/20100101 Firefox/78.0'} def初始化池: 全球会议 会话=s 获取单词的内容 def get_内容: r=session.getl,headers=headers soup=BeautifulSoupr.content,“html.parser” 条目\u name=soup。选择一个“文章标题\u 3-0”。内容[0] main=soup.select'.comp.article body.mntl block'[0] content=entry_name++'\n'++'\n'+strmain++'\n\n' 返回内容 并行计算 如果uuuu name uuuuu==\uuuuuuuu main\uuuuuuuu: 核心=操作系统cpu\u计数 会话=请求。会话 链接=['https://www.investopedia.com/terms/1/0x-protocol.asp', 'https://www.investopedia.com/terms/1/1-10net30.asp', 'https://www.investopedia.com/terms/1/10-k.asp', 'https://www.investopedia.com/terms/1/10k-wrap.asp', 'https://www.investopedia.com/terms/1/10q.asp'] p=poolprocesss=core,initializer=init_pool,initargs=session, content\u list=p.mapget\u内容、链接 content\u all=.joincontent\u列表 打印内容 冻结支持 但事实上,您的代码大部分时间都在等待URL被检索,而在处理返回的HTML时只花了一点CPU时间。这可能是使用多线程而不是多处理的一个很好的候选者。要使用多线程处理,您需要对原始代码进行的唯一更改是1删除所有引用以冻结支持,除非您计划创建一个exe文件并更改一条导入语句,否则多线程处理不需要这些引用:

来自multiprocessing.dummy导入池 此外,在确定要使用的线程数时,您不应受到CPU内核数的限制,尽管存在一些您不想超过的最大值:

导入请求,操作系统 从bs4导入BeautifulSoup 来自multiprocessing.dummy导入池 会话=请求。会话 headers={'User-Agent':'Mozilla/5.0 X11;Ubuntu;Linux x86_64;rv:78.0 Gecko/20100101 Firefox/78.0'} 链接=['https://www.investopedia.com/terms/1/0x-protocol.asp', 'https://www.investopedia.com/terms/1/1-10net30.asp', 'https://www.investopedia.com/terms/1/10-k.asp', 'https://www.investopedia.com/terms/1/10k-wrap.asp', 'https://www.investopedia.com/terms/1/10q.asp'] 获取单词的内容 def get_内容: r=session.getl,headers=headers soup=BeautifulSoupr.content,“html.parser” 条目\u name=soup。选择一个“文章标题\u 3-0”。内容[0] main=soup.select'.comp.article body.mntl block'[0] content=entry_name++'\n'++'\n'+strmain++'\n\n' 返回内容 并行计算 如果uuuu name uuuuu==\uuuuuuuu main\uuuuuuuu: 25的最大值是任意的;我们不希望出现拒绝服务攻击 P=poolprocesss=minlenlinks,25 content\u list=P.mapget\u内容、链接 content\u all=.joincontent\u列表 打印内容 最后,您可以结合使用线程池和多处理池来处理CPU密集型处理部分:

导入请求,操作系统 从bs4导入BeautifulSoup 来自multiprocessing.pool i mport线程池 从multiprocessing.pool导入池 导入操作系统 从functools导入部分 会话=请求。会话 headers={'User-Agent':'Mozilla/5.0 X11;Ubuntu;Linux x86_64;rv:78.0 Gecko/20100101 Firefox/78.0'} 链接=['https://www.investopedia.com/terms/1/0x-protocol.asp', 'https://www.investopedia.com/terms/1/1-10net30.asp', 'https://www.investopedia.com/terms/1/10-k.asp', 'https://www.investopedia.com/terms/1/10k-wrap.asp', 'https://www.investopedia.com/terms/1/10q.asp'] 获取单词的内容 def get_contentprocess_池,l: r=session.getl,headers=headers 返回进程\u pool.applyprocess\u内容,args=r.content, def过程内容: soup=BeautifulSoupcontent'html.parser' 条目\u name=soup。选择一个“文章标题\u 3-0”。内容[0] main=soup.select'.comp.article body.mntl block'[0] content=entry_name++'\n'++'\n'+strmain++'\n\n' 返回内容 并行计算 如果uuuu name uuuuu==\uuuuuuuu main\uuuuuuuu: 进程\u池=池进程=最小链接,os.cpu\u计数 线程池=线程池进程=最小链接,25 content\u list=thread\u pool.mappartialget\u内容、进程\u池、链接 content\u all=.joincontent\u列表 打印内容
首先,您的进口声明不正确,应该是:

从多处理导入池中,冻结\u支持 你有来自多进程的…,所以我根本不知道它是如何运行的

使用正确的import语句,代码可以为我运行,但它并不是您所认为的那样!我从冻结支持的电话中推测,您正在Windows下运行。在该平台下,通过调用系统函数spawn来调用新的进程,这将导致整个程序从最顶层执行。这就是为什么创建新进程的代码必须位于由if _uname _uu=='_umain _u':'控制的块中。如果不是这样,那么您新创建的进程将重新执行刚刚在一个永无止境的递归循环中创建它们的代码,从而永远产生新的进程

这意味着由于以下语句处于全局范围,每个进程正在重新创建自己的会话实例:

会话=请求。会话 因此,对于您试图检索的多个URL,能够重复使用同一会话实例并没有带来任何实际好处。为了重用同一个会话实例,必须使用会话对象初始化多处理池本身,使其驻留在共享内存中并对所有进程可见。您还应该只在全局范围内保留最小的可执行代码:

导入请求,操作系统 从bs4导入BeautifulSoup 从多处理导入池中,冻结\u支持 headers={'User-Agent':'Mozilla/5.0 X11;Ubuntu;Linux x86_64;rv:78.0 Gecko/20100101 Firefox/78.0'} def初始化池: 全球会议 会话=s 获取单词的内容 def get_内容: r=session.getl,headers=headers soup=BeautifulSoupr.content,“html.parser” 条目\u name=soup。选择一个“文章标题\u 3-0”。内容[0] main=soup.select'.comp.article body.mntl block'[0] content=entry_name++'\n'++'\n'+strmain++'\n\n' 返回内容 并行计算 如果uuuu name uuuuu==\uuuuuuuu main\uuuuuuuu: 核心=操作系统cpu\u计数 会话=请求。会话 链接=['https://www.investopedia.com/terms/1/0x-protocol.asp', 'https://www.investopedia.com/terms/1/1-10net30.asp', 'https://www.investopedia.com/terms/1/10-k.asp', 'https://www.investopedia.com/terms/1/10k-wrap.asp', 'https://www.investopedia.com/terms/1/10q.asp'] p=poolprocesss=core,initializer=init_pool,initargs=session, content\u list=p.mapget\u内容、链接 content\u all=.joincontent\u列表 打印内容 冻结支持 但事实上,您的代码大部分时间都在等待URL被检索,而在处理返回的HTML时只花了一点CPU时间。这可能是使用多线程而不是多处理的一个很好的候选者。要使用多线程处理,您需要对原始代码进行的唯一更改是1删除所有引用以冻结支持,除非您计划创建一个exe文件并更改一条导入语句,否则多线程处理不需要这些引用:

来自multiprocessing.dummy导入池 此外,在确定要使用的线程数时,您不应受到CPU内核数的限制,尽管存在一些您不想超过的最大值:

导入请求,操作系统 从bs4导入BeautifulSoup 来自multiprocessing.dummy导入池 会话=请求。会话 headers={'User-Agent':'Mozilla/5.0 X11;Ubuntu;Linux x86_64;rv:78.0 Gecko/20100101 Firefox/78.0'} 链接=['https://www.investopedia.com/terms/1/0x-protocol.asp', 'https://www.investopedia.com/terms/1/1-10net30.asp', 'https://www.investopedia.com/terms/1/10-k.asp', 'https://www.investopedia. com/terms/1/10k wrap.asp', 'https://www.investopedia.com/terms/1/10q.asp'] 获取单词的内容 def get_内容: r=session.getl,headers=headers soup=BeautifulSoupr.content,“html.parser” 条目\u name=soup。选择一个“文章标题\u 3-0”。内容[0] main=soup.select'.comp.article body.mntl block'[0] content=entry_name++'\n'++'\n'+strmain++'\n\n' 返回内容 并行计算 如果uuuu name uuuuu==\uuuuuuuu main\uuuuuuuu: 25的最大值是任意的;我们不希望出现拒绝服务攻击 P=poolprocesss=minlenlinks,25 content\u list=P.mapget\u内容、链接 content\u all=.joincontent\u列表 打印内容 最后,您可以结合使用线程池和多处理池来处理CPU密集型处理部分:

导入请求,操作系统 从bs4导入BeautifulSoup 从multiprocessing.pool导入线程池 从multiprocessing.pool导入池 导入操作系统 从functools导入部分 会话=请求。会话 headers={'User-Agent':'Mozilla/5.0 X11;Ubuntu;Linux x86_64;rv:78.0 Gecko/20100101 Firefox/78.0'} 链接=['https://www.investopedia.com/terms/1/0x-protocol.asp', 'https://www.investopedia.com/terms/1/1-10net30.asp', 'https://www.investopedia.com/terms/1/10-k.asp', 'https://www.investopedia.com/terms/1/10k-wrap.asp', 'https://www.investopedia.com/terms/1/10q.asp'] 获取单词的内容 def get_contentprocess_池,l: r=session.getl,headers=headers 返回进程\u pool.applyprocess\u内容,args=r.content, def过程内容: soup=BeautifulSoupcontent'html.parser' 条目\u name=soup。选择一个“文章标题\u 3-0”。内容[0] main=soup.select'.comp.article body.mntl block'[0] content=entry_name++'\n'++'\n'+strmain++'\n\n' 返回内容 并行计算 如果uuuu name uuuuu==\uuuuuuuu main\uuuuuuuu: 进程\u池=池进程=最小链接,os.cpu\u计数 线程池=线程池进程=最小链接,25 content\u list=thread\u pool.mappartialget\u内容、进程\u池、链接 content\u all=.joincontent\u列表 打印内容
关于主进程中的对象如何与孩子共享的另一个问题,请参阅我的。关于主进程中的对象如何与孩子共享的另一个问题,请参阅我的。现在我感觉到并行计算的复杂性,并理解了为什么现在大多数游戏无法利用芯片中的大量CPU。非常感谢您的大力帮助!我是说。。。。。先试试DOS,如果你被禁赛一个小时,就退后一步;我添加了第三个编码示例,它将线程池与多处理池结合起来,只是为了说明这是可能的。现在我感觉到并行计算的复杂性,并理解了为什么现在大多数游戏无法利用芯片中的大量CPU。非常感谢您的大力帮助!我是说。。。。。先试试DOS,如果你被禁赛一个小时,就退后一步;我添加了第三个编码示例,该示例将线程池与多处理池相结合,以表明这是可能的。