Python 如何在命令行中为池进程创建进度条?

Python 如何在命令行中为池进程创建进度条?,python,python-multiprocessing,Python,Python Multiprocessing,我有几个使用多处理池运行的脚本,我正在尝试根据完成的脚本创建一个进度条 我查过了 但我不知道如何组合在计数器中完成的脚本 import os from multiprocessing import Pool def run_process(process):

我有几个使用多处理池运行的脚本,我正在尝试根据完成的脚本创建一个进度条

我查过了


但我不知道如何组合在计数器中完成的脚本

import os                                                                       
from multiprocessing import Pool

def run_process(process):                                                             
    os.system('python {}'.format(process))

processes = ('script1.py', 'script2.py','script3.py','script4.py')

if __name__ == "__main__":

    pool = Pool(processes=2)
    pool.map(run_process, processes)
您可以通过使用来实现这一点,因为它支持一个回调函数,可用于知道目标函数何时返回

我使用@Greenstick's来显示进度条,但我对其进行了修改,主要是为了符合PEP-8编码准则,并将其放置在名为
print\u progress\u bar
的单独模块中-见下文

性能说明:虽然可以使用
多处理.Pool
来实现这一点-我强烈怀疑您问题中的代码是文章内容的逐字复制-这样做效率极低,因为每个进程将初始化自己的Python解释器实际次数加倍必要的。首先执行
run\u process()
函数本身,然后再次运行脚本进程

产卵过程涉及相当大的开销。这种开销可以通过在当前进程中作为单独的线程运行
run\u process()
来减轻,这是一种较轻的方法

切换到
ThreadPool
非常简单,只需更改行:
来自多处理导入池的


从multiprocessing.pool导入ThreadPool作为池

或者,您可以使用
concurrent.futures.ThreadPoolExecutor
,如my中所示


打印进度条.py

# from https://stackoverflow.com/a/34325723/355230
def print_progress_bar(iteration, total, prefix='', suffix='', decimals=1, length=100,
                       fill='█', print_end="\r"):
    """ Print iterations progress.

        Call in a loop to create terminal progress bar
        @params:
            iteration   - Required  : current iteration (Int)
            total       - Required  : total iterations (Int)
            prefix      - Optional  : prefix string (Str)
            suffix      - Optional  : suffix string (Str)
            decimals    - Optional  : positive number of decimals in percent complete (Int)
            length      - Optional  : character length of bar (Int)
            fill        - Optional  : bar fill character (Str)
            print_end   - Optional  : end character (e.g. "\r", "\r\n") (Str)
    """
    percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
    filledLength = int(length * iteration // total)
    bar = fill * filledLength + '-' * (length - filledLength)
    print('\r%s |%s| %s%% %s' % (prefix, bar, percent, suffix), end=print_end, flush=True)

    if iteration == total:  # Print newline on completion.
        print(flush=True)

您可以通过使用来实现这一点,因为它支持一个回调函数,可用于知道目标函数何时返回

我使用@Greenstick's来显示进度条,但我对其进行了修改,主要是为了符合PEP-8编码准则,并将其放置在名为
print\u progress\u bar
的单独模块中-见下文

性能说明:虽然可以使用
多处理.Pool
来实现这一点-我强烈怀疑您问题中的代码是文章内容的逐字复制-这样做效率极低,因为每个进程将初始化自己的Python解释器实际次数加倍必要的。首先执行
run\u process()
函数本身,然后再次运行脚本进程

产卵过程涉及相当大的开销。这种开销可以通过在当前进程中作为单独的线程运行
run\u process()
来减轻,这是一种较轻的方法

切换到
ThreadPool
非常简单,只需更改行:
来自多处理导入池的


从multiprocessing.pool导入ThreadPool作为池

或者,您可以使用
concurrent.futures.ThreadPoolExecutor
,如my中所示


打印进度条.py

# from https://stackoverflow.com/a/34325723/355230
def print_progress_bar(iteration, total, prefix='', suffix='', decimals=1, length=100,
                       fill='█', print_end="\r"):
    """ Print iterations progress.

        Call in a loop to create terminal progress bar
        @params:
            iteration   - Required  : current iteration (Int)
            total       - Required  : total iterations (Int)
            prefix      - Optional  : prefix string (Str)
            suffix      - Optional  : suffix string (Str)
            decimals    - Optional  : positive number of decimals in percent complete (Int)
            length      - Optional  : character length of bar (Int)
            fill        - Optional  : bar fill character (Str)
            print_end   - Optional  : end character (e.g. "\r", "\r\n") (Str)
    """
    percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
    filledLength = int(length * iteration // total)
    bar = fill * filledLength + '-' * (length - filledLength)
    print('\r%s |%s| %s%% %s' % (prefix, bar, percent, suffix), end=print_end, flush=True)

    if iteration == total:  # Print newline on completion.
        print(flush=True)


这里有一个稍微不同的方法,它使用而不是
多处理.Pool
,它比我的

注意它使用与我的另一个答案相同的
打印进度条.py
模块

import concurrent.futures
import os
import subprocess
import sys

from print_progress_bar import print_progress_bar
progress_bar_kwargs = dict(prefix='Progress:', suffix='Complete', length=40)

# To simplify testing just using one script multiple times.
processes = ('./mp_scripts/script1.py', './mp_scripts/script1.py',
             './mp_scripts/script1.py', './mp_scripts/script1.py')
process_count = 0


def run_process(process):
    global process_count

    subprocess.run([sys.executable,  process])
    # Update process count and progress bar when it's done.
    process_count += 1
    print_progress_bar(process_count, len(processes), **progress_bar_kwargs)


print_progress_bar(0, len(processes), **progress_bar_kwargs) # Print 0% progress.
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:

    future_to_process = {executor.submit(run_process, process): process
                            for process in processes}
    for future in concurrent.futures.as_completed(future_to_process):
        process = future_to_process[future]
        try:
            _ = future.result()
        except Exception as exc:
            print()
            print(f'{process} generated an exception: {exc}')

    print('Done')

这里有一个稍微不同的方法,它使用而不是
多处理.Pool
,它比我的

注意它使用与我的另一个答案相同的
打印进度条.py
模块

import concurrent.futures
import os
import subprocess
import sys

from print_progress_bar import print_progress_bar
progress_bar_kwargs = dict(prefix='Progress:', suffix='Complete', length=40)

# To simplify testing just using one script multiple times.
processes = ('./mp_scripts/script1.py', './mp_scripts/script1.py',
             './mp_scripts/script1.py', './mp_scripts/script1.py')
process_count = 0


def run_process(process):
    global process_count

    subprocess.run([sys.executable,  process])
    # Update process count and progress bar when it's done.
    process_count += 1
    print_progress_bar(process_count, len(processes), **progress_bar_kwargs)


print_progress_bar(0, len(processes), **progress_bar_kwargs) # Print 0% progress.
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:

    future_to_process = {executor.submit(run_process, process): process
                            for process in processes}
    for future in concurrent.futures.as_completed(future_to_process):
        process = future_to_process[future]
        try:
            _ = future.result()
        except Exception as exc:
            print()
            print(f'{process} generated an exception: {exc}')

    print('Done')

“合并在计数器中完成的脚本”太模糊了。计数器到底应该代表什么?计数器统计完成的脚本到目前为止,为什么要通过
os.system
运行其他Python程序,而不是使用标准的机制,例如导入模块的能力?@MiaoulisNikos计数器统计完成的脚本到目前为止,我不确定我是否理解问题所在,然后,
pool.map()
阻塞,直到所有进程都完成,因此没有指示单个进程何时完成-因此无法用进度条显示到目前为止已完成的进程数。“在计数器中合并已完成的脚本”太模糊了。计数器到底应该代表什么?计数器统计完成的脚本到目前为止,为什么要通过
os.system
运行其他Python程序,而不是使用标准的机制,例如导入模块的能力?@MiaoulisNikos计数器统计完成的脚本到目前为止,我不确定我是否理解问题所在,然后,
pool.map()
会一直阻塞,直到所有进程都完成,因此没有指示单个进程何时完成-因此您无法使用progressbar显示到目前为止已完成的进程数。