os.system调用像串行执行多线程一样运行

问题描述 投票:0回答:1

我的同事问我为什么他的代码不能多线程并发运行。我发现

os.system
函数的行为与多线程中的其他函数不同。我编写了一个小演示来重现该问题。感谢能够回答我问题的人。

像串行执行一样运行

import os
import time

from concurrent.futures import ThreadPoolExecutor, as_completed

executor = ThreadPoolExecutor()
begin = time.time()

for _ in as_completed([
        executor.submit(os.system, cmd)
        for cmd in ['sleep 10', 'sleep 3', 'sleep 2']
    ]):
    print("completed after", time.time() - begin, "seconds")

输出

completed after 10.005892276763916 seconds
completed after 13.017478942871094 seconds
completed after 15.034425258636475 seconds

正常运行

os.system
替换为
subprocess.call

import subprocess
import time

from concurrent.futures import ThreadPoolExecutor, as_completed

executor = ThreadPoolExecutor()
begin = time.time()

for _ in as_completed([
        executor.submit(subprocess.call, cmd, shell=True)
        for cmd in ['sleep 10', 'sleep 3', 'sleep 2']
    ]):
    print("completed after", time.time() - begin, "seconds")

输出

completed after 2.019604206085205 seconds
completed after 3.017033338546753 seconds
completed after 10.009897232055664 seconds
python multithreading subprocess system-calls
1个回答
1
投票

os.system
是通过调用标准C函数实现的
system
:

这是通过调用标准C函数

system()
来实现的,并且 具有相同的限制。

根据

system
函数的手册页:

在等待子进程终止时阻塞

SIGCHLD
可以防止 应用程序捕获信号并获取状态
system()
的子进程在
system()
之前可以获取状态本身。

和:

在进程中的多个线程中使用

system()
函数或 当
SIGCHLD
信号被多个线程操作时 在一个过程中可能会产生意想不到的结果。

由于

SIGCHLD
在执行过程中必须被阻塞,所以并发调用
system
是行不通的。

另一方面,

subprocess.Popen
subprocess.call
函数使用的底层类)在不阻塞
fork
的情况下处理
exec
/
wait
/
SIGCHLD
,因此可以并发执行。

© www.soinside.com 2019 - 2024. All rights reserved.