Python 子进程-线程数

Python 子进程-线程数,python,multithreading,multiprocessing,Python,Multithreading,Multiprocessing,run.py scan.py def work(repo,cpuid): my_tool_subprocess = subprocess.Popen('./scan.py {} {}'.format(repo,cpuid),shell=True, stdout=subprocess.PIPE) line = True while line: myline = my_tool_subprocess.stdout.readline() if "

run.py

scan.py

def work(repo,cpuid):
    my_tool_subprocess = subprocess.Popen('./scan.py {} {}'.format(repo,cpuid),shell=True, stdout=subprocess.PIPE)
    line = True
    while line:
        myline = my_tool_subprocess.stdout.readline()
        if "scan is done" in myline:
            break

num = 10  # set to the number of workers you want (it defaults to the cpu count of your machine)
tp = ThreadPool(num)
cpuid=1
for repo in repos:
    tp.apply_async(work, (repo[0],"1-240"))
    print('Runing {} at core {}'.format(repo[0],"1-240"))
tp.close()
tp.join()
我原以为活动进程的数量是10(10个线程),但不知怎的。。。事实并非如此。似乎它不会等到scan.py中的最后一条语句“scan is done”,而是遍历repo列表(for loop),从repos列表克隆所有repo。重复一次,它不需要等待第1-10次回购被克隆和处理(保持10个过程的移动窗口),它只需要。。。创建其他进程和repos克隆


有人知道这里出了什么问题吗?

试着像这样重构代码:

scan.py
中,将所有模块级代码移动到一个函数中,例如:

 completed = subprocess.run(['git', 'clone', repo],env=my_env)
 bunch of other subprocess.run()

 # at the end:

 print('returncode:', completed.returncode)
 print('scan is done')
如果您仍然关心
scan.py
是否还有命令行界面,请添加:

def run(repo, cpuid):
    # do whatever scan.py does given a repo path and cpuid
    # instead of printing to stdout, have this return a value
现在在您的
run.py
中执行以下操作:

import argparse

def main(argv=None):
    parser = argparse.ArgumentParser()
    # ... implement command-line argument parsing here
    args = parser.parse_args(argv)
    value = run(args.repo, args.cpuid)
    print(value)

if __name__ == '__main__':
    main()

像这样的。我想在这里指出的一点是,如果您明智地考虑代码,它将使多处理变得更加简单。然而,这里的一些细节有点自以为是。

试着像这样重构代码:

scan.py
中,将所有模块级代码移动到一个函数中,例如:

 completed = subprocess.run(['git', 'clone', repo],env=my_env)
 bunch of other subprocess.run()

 # at the end:

 print('returncode:', completed.returncode)
 print('scan is done')
如果您仍然关心
scan.py
是否还有命令行界面,请添加:

def run(repo, cpuid):
    # do whatever scan.py does given a repo path and cpuid
    # instead of printing to stdout, have this return a value
现在在您的
run.py
中执行以下操作:

import argparse

def main(argv=None):
    parser = argparse.ArgumentParser()
    # ... implement command-line argument parsing here
    args = parser.parse_args(argv)
    value = run(args.repo, args.cpuid)
    print(value)

if __name__ == '__main__':
    main()

像这样的。我想在这里指出的一点是,如果您明智地考虑代码,它将使多处理变得更加简单。但是,这里的一些细节有点自以为是。

为什么要启动启动子进程的线程,而不是只使用
多处理.Pool
?特别是考虑到您只是在运行Python脚本
scan.py
。线程池是什么?
ThreadPool
?我需要克隆repo,等待它被克隆,然后依次运行命令,下一个命令需要完成上一个命令,此时最多10个进程(10 x scan.py)。您可以参考一些示例吗?为什么要启动启动子进程的线程,而不是只使用
多处理.Pool
?特别是考虑到您只是在运行Python脚本
scan.py
。线程池是什么?
ThreadPool
?我需要克隆repo,等待它被克隆,然后依次运行命令,下一个命令需要完成上一个命令,此时最多10个进程(10 x scan.py)。你能举出一些例子吗?谢谢。我很快就会试一试。在run()中,我可以按顺序调用subprocess.run(),对吗?是的,如果您正在运行多个命令并收集它们的标准输出,您可能希望将每个stdout添加到返回的列表中,或者您可以将其放入生成器函数中,并
在运行时产生
每一行输出,然后像运行中的行那样调用它(…):打印(行)
。谢谢。我很快就会试一试。在run()中,我可以按顺序调用subprocess.run(),对吗?是的,如果您正在运行多个命令并收集它们的标准输出,您可能希望将每个stdout添加到返回的列表中,或者您可以将其放入生成器函数中,并
在运行时产生
每一行输出,然后像运行中的行那样调用它(…):打印(行)