我总是使用“多处理”本机库来处理 Python 中的并行性。为了控制队列中的进程数,我使用共享变量作为计数器。在以下示例中,您可以看到简单流程的并行执行是如何工作的。您需要安装的唯一库是“coloredlogs”。
代码
# pip install coloredlogs==15.0.1
from multiprocessing import Pool, Manager, Value, cpu_count
from datetime import datetime
import coloredlogs
import logging
import time
import sys
LOG_LEVEL = "DEBUG"
def setup_logger(name: str = __name__, level: str = LOG_LEVEL) -> logging.Logger:
assert level in ["NOTSET", "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
logging.basicConfig(
format="%(asctime)s %(name)s[%(process)d] %(levelname)s %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
level=level,
handlers=[logging.StreamHandler()]
)
logger = logging.getLogger(name)
coloredlogs.install(level=level, logger=logger, isatty=True)
return logger
def execute_process(name: str, queue: Value) -> None:
logger = setup_logger()
logger.info(f"Executing process: {name}...")
time.sleep(5)
queue.value -= 1
def create_processes(processes_names: [str], n_jobs: int = -1, waiting_time: int = 1) -> None:
logger = setup_logger()
if n_jobs <= 0:
n_jobs = cpu_count()
manager = Manager()
pool = Pool(processes=n_jobs)
queue = manager.Value('i', 0)
lock = manager.Lock()
start_time = datetime.now()
with lock: # Protecting the processes' queue shared variable.
for name in processes_names:
while True:
if queue.value < n_jobs:
queue.value += 1
# Creating processes in parallel:
pool.apply_async(
func=execute_process,
args=(name, queue)
)
break
else:
logger.debug(f"Pool full ({n_jobs}): waiting {waiting_time} seconds...")
time.sleep(waiting_time)
pool.close()
pool.join()
exec_time = datetime.now() - start_time
logger.info(f"Execution time: {exec_time}")
if __name__ == '__main__':
processes_names = ["A", "B", "C", "D", "E", "F"]
n_jobs = int(sys.argv[1]) # Number of jobs to run in parallel.
# Creating and executing processes in parallel:
create_processes(processes_names=processes_names, n_jobs=n_jobs)
执行与输出
user@host:~$ python run.py 1
2021-12-23 12:41:51 MYMACHINE __main__[24180] DEBUG Pool full (1): waiting 1 seconds...
2021-12-23 12:41:51 MYMACHINE __mp_main__[12352] INFO Executing process: A...
2021-12-23 12:41:52 MYMACHINE __main__[24180] DEBUG Pool full (1): waiting 1 seconds...
2021-12-23 12:41:53 MYMACHINE __main__[24180] DEBUG Pool full (1): waiting 1 seconds...
2021-12-23 12:41:54 MYMACHINE __main__[24180] DEBUG Pool full (1): waiting 1 seconds...
2021-12-23 12:41:55 MYMACHINE __main__[24180] DEBUG Pool full (1): waiting 1 seconds...
2021-12-23 12:41:56 MYMACHINE __main__[24180] DEBUG Pool full (1): waiting 1 seconds...
2021-12-23 12:41:57 MYMACHINE __main__[24180] DEBUG Pool full (1): waiting 1 seconds...
2021-12-23 12:41:57 MYMACHINE __mp_main__[12352] INFO Executing process: B...
2021-12-23 12:41:58 MYMACHINE __main__[24180] DEBUG Pool full (1): waiting 1 seconds...
2021-12-23 12:41:59 MYMACHINE __main__[24180] DEBUG Pool full (1): waiting 1 seconds...
2021-12-23 12:42:00 MYMACHINE __main__[24180] DEBUG Pool full (1): waiting 1 seconds...
...
2021-12-23 12:42:10 MYMACHINE __main__[24180] DEBUG Pool full (1): waiting 1 seconds...
2021-12-23 12:42:11 MYMACHINE __main__[24180] DEBUG Pool full (1): waiting 1 seconds...
2021-12-23 12:42:12 MYMACHINE __main__[24180] DEBUG Pool full (1): waiting 1 seconds...
2021-12-23 12:42:12 MYMACHINE __mp_main__[12352] INFO Executing process: E...
2021-12-23 12:42:13 MYMACHINE __main__[24180] DEBUG Pool full (1): waiting 1 seconds...
2021-12-23 12:42:14 MYMACHINE __main__[24180] DEBUG Pool full (1): waiting 1 seconds...
2021-12-23 12:42:15 MYMACHINE __main__[24180] DEBUG Pool full (1): waiting 1 seconds...
2021-12-23 12:42:16 MYMACHINE __main__[24180] DEBUG Pool full (1): waiting 1 seconds...
2021-12-23 12:42:18 MYMACHINE __mp_main__[12352] INFO Executing process: F...
2021-12-23 12:42:23 MYMACHINE __main__[24180] INFO Execution time: 0:00:31.274478
user@host:~$ python run.py 3
2021-12-23 12:33:59 MYMACHINE __main__[7628] DEBUG Pool full (3): waiting 1 seconds...
2021-12-23 12:33:59 MYMACHINE __mp_main__[19776] INFO Executing process: A...
2021-12-23 12:33:59 MYMACHINE __mp_main__[24632] INFO Executing process: B...
2021-12-23 12:33:59 MYMACHINE __mp_main__[15852] INFO Executing process: C...
2021-12-23 12:34:00 MYMACHINE __main__[7628] DEBUG Pool full (3): waiting 1 seconds...
2021-12-23 12:34:01 MYMACHINE __main__[7628] DEBUG Pool full (3): waiting 1 seconds...
2021-12-23 12:34:02 MYMACHINE __main__[7628] DEBUG Pool full (3): waiting 1 seconds...
2021-12-23 12:34:03 MYMACHINE __main__[7628] DEBUG Pool full (3): waiting 1 seconds...
2021-12-23 12:34:04 MYMACHINE __main__[7628] DEBUG Pool full (3): waiting 1 seconds...
2021-12-23 12:34:05 MYMACHINE __mp_main__[19776] INFO Executing process: D...
2021-12-23 12:34:05 MYMACHINE __mp_main__[24632] INFO Executing process: E...
2021-12-23 12:34:05 MYMACHINE __mp_main__[15852] INFO Executing process: F...
2021-12-23 12:34:10 MYMACHINE __main__[7628] INFO Execution time: 0:00:11.087672
user@host:~$ python run.py 6
2021-12-23 12:40:48 MYMACHINE __mp_main__[26312] INFO Executing process: A...
2021-12-23 12:40:48 MYMACHINE __mp_main__[11468] INFO Executing process: B...
2021-12-23 12:40:48 MYMACHINE __mp_main__[12000] INFO Executing process: C...
2021-12-23 12:40:48 MYMACHINE __mp_main__[19864] INFO Executing process: D...
2021-12-23 12:40:48 MYMACHINE __mp_main__[25356] INFO Executing process: E...
2021-12-23 12:40:48 MYMACHINE __mp_main__[14504] INFO Executing process: F...
2021-12-23 12:40:53 MYMACHINE __main__[1180] INFO Execution time: 0:00:05.295934