Python 用OSX编写脚本,具有多处理功能。现在windows赢了';我不打球

Python 用OSX编写脚本,具有多处理功能。现在windows赢了';我不打球,python,windows,multiprocessing,pool,Python,Windows,Multiprocessing,Pool,我制作的程序/脚本可以在OSX和linux上运行。它使用selenium从一些页面中刮取数据,处理数据并保存数据。为了提高效率,我加入了多处理池和管理器。我为列表中的每个项目创建一个池,它调用scrape类,启动一个phantomjs实例并进行scrape。由于我使用的是multiprocessing.pool,并且我想要一种在线程之间传递数据的方法,因此我了解到multiprocessing.manager是前进的方向。如果我写 manager=manager() info=manager.d

我制作的程序/脚本可以在OSX和linux上运行。它使用selenium从一些页面中刮取数据,处理数据并保存数据。为了提高效率,我加入了多处理池和管理器。我为列表中的每个项目创建一个池,它调用scrape类,启动一个phantomjs实例并进行scrape。由于我使用的是multiprocessing.pool,并且我想要一种在线程之间传递数据的方法,因此我了解到multiprocessing.manager是前进的方向。如果我写
manager=manager()
info=manager.dict([])
它将创建一个可以被所有线程访问的dict。这一切都很完美

我的问题是,客户端希望在windows机器上运行它(我在OSX上编写了整个程序),我假设,安装python、selenium并启动它就很简单了。我有一些错误,后来导致我在main.py文件的顶部写入
if uuuu name_uuuu='\uuuu main:
,并缩进要放入的所有内容。问题是,当if语句之外有
class scrap():
时,它无法看到全局信息,因为它在范围之外声明。如果我在
中插入
类scrape():
如果uuu name\uuuu=='\uuuu main\uuuu':
则会得到一个属性错误

AttributeError:“模块”对象没有属性“刮取”

如果我回到声明manager=manager()和info=manager.dict([])之外的
if uuu name uuu='.\uu main uu'
,那么我会在windows中得到一个错误,那就是确保我使用
if uu name u='.\uu main u'
,目前看来我无法赢得这个项目

代码布局

Imports...
from multiprocessing import Pool
from multiprocessing import Manager

manager = Manager()
info = manager.dict([])
date = str(datetime.date.today())

class do_scrape():
    def __init__():
    def...

def scrape_items():#This contains code which creates a pool and then pool.map(do_scrape, s) s = a list of items

def save_scrape():

def update_price():

def main():

main()

基本上,scrape_项由main调用,然后scrape_项使用pool.map(do_scrape,s),因此它调用do_scrape类并将项列表逐个传递给它。do_scrape然后根据“s”中的项目url刮取网页,然后将该信息保存在全局信息中,即multiprocessing.manager dict。上面的代码不显示任何
如果uuuu name_uuuuu=='uuuu main_uuuuuu':
语句,它是如何在我的OSX设置中工作的概述。它按原样运行并完成任务。如果有人能提出一些建议,我将不胜感激。谢谢

查看您的代码会很有帮助,但听起来您只需要将共享的dict显式地传递给
scrape
,如下所示:

import multiprocessing
from functools import partial

def scrape(info, item):
   # Use info in here

if __name__ == "__main__":
   manager = multiprocessing.Manager()
   info = manager.dict()
   pool = multiprocessing.Pool()
   func = partial(scrape, info) # use a partial to make it easy to pass the dict to pool.map
   items = [1,2,3,4,5] # This would be your actual data
   results = pool.map(func, items)
   #pool.apply_async(scrape, [shared_dict, "abc"]) # In case you're not using map...
请注意,如果uuu name uuuuu==“uuuu main uuuuuuuu”:guard,则不应将所有代码放在
中,而应放在通过
多处理
实际创建进程的代码中,这包括创建
管理器

您希望在子进程中运行的任何方法都必须在模块的顶层声明,因为它必须可以从子进程中的
\uuuuu main\uuuuuu
导入。当您在
if _; name)
保护内声明
scrape
时,它无法再从
主模块导入,因此您看到了
AttributeError:“module”对象没有属性“scrape”
错误

编辑:

以你为例:

import multiprocessing
from functools import partial

date = str(datetime.date.today())

#class do_scrape():
#    def __init__():
#    def...
def do_scrape(info, s):
    # do stuff
    # Also note that do_scrape should probably be a function, not a class

def scrape_items():
    # scrape_items is called by main(), which is protected by a`if __name__ ...` guard 
    # so this is ok.
    manager = multiprocessing.Manager()
    info = manager.dict([])
    pool = multiprocessing.Pool()
    func = partial(do_scrape, info) 
    s = [1,2,3,4,5] # Substitute with the real s
    results = pool.map(func, s)     

def save_scrape():

def update_price():

def main():
    scrape_items()

if __name__ == "__main__": 
    # Note that you can declare manager and info here, instead of in scrape_items, if you wanted
    #manager = multiprocessing.Manager()
    #info = manager.dict([])
    main()
Imports...
from multiprocessing import Pool
from multiprocessing import Manager

manager = Manager()
info = manager.dict([])
date = str(datetime.date.today())

class do_scrape():
    def __init__():
    def...

def scrape_items():#This contains code which creates a pool and then pool.map(do_scrape, s) s = a list of items

def save_scrape():

def update_price():

def main():

if __name__ == "__main__":
    main()

另一个重要的注意事项是,
map
的第一个参数应该是一个函数,而不是一个类。这在(
multiprocessing.map
相当于内置的map)中有说明。

找到程序的起点,并确保用
if
语句仅包装该起点。例如:

import multiprocessing
from functools import partial

date = str(datetime.date.today())

#class do_scrape():
#    def __init__():
#    def...
def do_scrape(info, s):
    # do stuff
    # Also note that do_scrape should probably be a function, not a class

def scrape_items():
    # scrape_items is called by main(), which is protected by a`if __name__ ...` guard 
    # so this is ok.
    manager = multiprocessing.Manager()
    info = manager.dict([])
    pool = multiprocessing.Pool()
    func = partial(do_scrape, info) 
    s = [1,2,3,4,5] # Substitute with the real s
    results = pool.map(func, s)     

def save_scrape():

def update_price():

def main():
    scrape_items()

if __name__ == "__main__": 
    # Note that you can declare manager and info here, instead of in scrape_items, if you wanted
    #manager = multiprocessing.Manager()
    #info = manager.dict([])
    main()
Imports...
from multiprocessing import Pool
from multiprocessing import Manager

manager = Manager()
info = manager.dict([])
date = str(datetime.date.today())

class do_scrape():
    def __init__():
    def...

def scrape_items():#This contains code which creates a pool and then pool.map(do_scrape, s) s = a list of items

def save_scrape():

def update_price():

def main():

if __name__ == "__main__":
    main()
实际上,只有在运行python代码时直接调用此文件时,才会执行
if
的内容。如果此文件/模块作为从另一个文件的导入包含,则将定义所有属性,因此您可以访问各种属性,而无需实际开始执行模块

请在此处阅读更多信息:

添加一些代码框架,显示类管理器的位置、类刮取、全局变量和您使用的行:if name=='main您应该重新考虑添加
if.\u name.'u=='main:
的原因。我看不出只有Windows才需要这样做的原因,而且很可能有更好的方法。@MartinKonecny当我在Windows机器上运行上述代码时,我得到的错误是“尝试在当前进程完成引导阶段之前启动新进程。这可能意味着您在Windows上,而您忘记了在主模块中使用正确的习惯用法:if name='main':free_support()…@MartinKonecny在其他平台上没有的地方,Windows上绝对需要使用
if_uuuname\uuu
guard。它在@dano中解释了这一点,谢谢你提供的信息。谢谢你,不过我对python还不熟悉,不完全理解这个解决方案。我尝试了functools中的部分函数,但没有乐趣。@user3387507您能更具体地说明“没有乐趣”的含义吗?我不能,因为我不完全理解解决方案。我显然做错了什么。@user3387507我更新了我的答案,使其看起来更像您的示例代码。也许这会有帮助。谢谢你编辑的代码。“do_scrape”应该是scrape,我更改了它,因为我读到如果我在目录中有一个名为scrape.py的文件,它可能是一个解决方案。scrape类具有不同的函数,用于刮取不同的内容等。。。这就是为什么它是一门课。这个解决方案似乎是最接近的,但是我现在得到了一个酸洗错误。“multiprocessing.pool.MaybeEncodingError:发送结果时出错”。scrape instance“Reason UnpickleAbleError我尝试了此解决方案,但仍然遇到相同的错误,即需要if name='main”:请确保使用
if\u name='\uu main\uu='
块包装启动多进程的代码,以澄清-如果包装整个代码如果使用
if name==main
,则如果从另一个模块导入,则文件基本上是空的/无用的(如果
if
语句的计算结果将为false)<