【问题标题】:Python3 subprocess in multiprocessing多处理中的Python3子进程
【发布时间】:2019-01-09 13:30:02
【问题描述】:

我是编写并发代码的初学者。

我正在编写一个获取用户 ID 并尝试返回用户全名的代码,查询需要一秒钟左右的时间来执行,所以我希望涉及多处理以更快地收集数据;我想我已经接近了,但我不明白框架需要如何正确实现。

from subprocess import getoutput
from multiprocessing import Pool

all_users = ['User1', 'User2', 'User3', 'User4', 'User5', 'User6'] # example list

def get_name(userid):
    name = getoutput('net users {} /domain | findstr "full name:"'.format(userid)).replace('Full Name', '').strip().split('\n')[0]
    return {userid : name}


if __name__ == '__main__':
    with Pool(4) as p:
        print(p.map(get_name, all_users))

    print(' --------- finished')

print(' - exiting - '))

这只是多步骤脚本中的一个步骤;输出如下:(忽略“找不到用户名”部分,仅举例)

 - exiting -
 - exiting -
 - exiting -
 - exiting -
[{'User1': 'The user name could not be found.'}, {'User2': 'The user name could not be found.'}, {'User3': 'The user name could not be found.'}, {'User4': 'The user name could not be found.'}, {'User5': 'The user name could not be found.'}, {'User6': 'The user name could not be found.'}]
 --------- finished
 - exiting -

我正在尝试按如下方式构建程序:

  1. 获取用户列表
  2. 将 ID 转换为名称(尽快为每个函数调用生成一个单独的进程)
  3. 等待第二步完全完成,然后处理返回的数据;

我尝试从各种来源阅读该主题,但我无法以某种方式掌握结构......据我所知,由于我有 4 个核心,我在开始时收到了四个 - 退出 - 语句,但是我如何封装这部分代码,以便在它运行时不会发生任何其他事情,并且 - 退出 - 在它的末尾只写一次。

【问题讨论】:

标签: python python-3.x concurrency python-multiprocessing


【解决方案1】:

您需要在 with 循环中使用 pool.close() 语句:

with Pool(4) as p:
    print(p.map(get_name, all_users))
    p.close()

【讨论】:

  • “with”语句不应该自动处理Pool对象的关闭吗?
【解决方案2】:

以下链接回答了类似的问题: multiple output returned from python multiprocessing function

总结一下:

# Import stuff
#If the worker code is in the main thread, exclude it from the if statement:
def worker():
    #worker code
if __name__ == '__main__':
    #execute whatever you want, it will only be executed 
    #as often as you intend it to
    #execute the function that starts multiprocessing, 

#All code outside of the if statement will be executed multiple times
#depending on the # of assigned worker threads.

【讨论】:

    【解决方案3】:

    Josh Hayes 已经给出了正确的答案。如果你像这样使用池,它会在退出时调用terminatehttps://docs.python.org/3.4/library/multiprocessing.html?highlight=process),因为 Python 3.3。您必须添加 p.close() 才能正确完成。但是,您的最后一个括号太多了,您不应看到多个 finishedexiting 打印,因为这些调用不在池中。你如何开始你的脚本?您使用的是哪个 Python 版本?

    编辑: 您可以尝试添加:

    import os
    
    def info(title):
        print(title)
        print('module name:', __name__)
        print('parent process:', os.getppid())
        print('process id:', os.getpid())
    
    all_users = ['User1', 'User2', 'User3', 'User4', 'User5', 'User6'] # example list
    
    def get_name(userid):
        name = getoutput('net users {} /domain | findstr "full name:"'.format(userid)).replace('Full Name', '').strip().split('\n')[0]
        print(info("p "))
        return {userid : name}
    

    并调用info("whatever") 而不是exiting 并查看哪些进程在此处工作。 您使用的是哪个操作系统?至少在 Linux 上是有意义的。

    【讨论】:

    • 我使用的是 Python 3.6.3 x64;这确实是我粘贴的整个脚本,输出很奇怪......开始时有 4 个退出语句,然后脚本运行,然后其余的事情按顺序发生;附言“with”语句不处理Pool对象的自动关闭吗?
    • 我有点困惑。我使用 Python 3.5.2 对其进行了测试,我的进程没有终止,主进程正在等待所有进程完成。但是,在文档中它声明 terminate() Stops the worker processes immediately without completing outstanding work. When the pool object is garbage collected terminate() will be called immediately. 3.3 版中的新功能:池对象现在支持上下文管理协议 - 请参阅上下文管理器类型。 __enter__() 返回池对象,__exit__() 调用 terminate()。
    猜你喜欢
    • 1970-01-01
    • 2023-04-02
    • 2020-02-27
    • 2014-11-12
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多