os.system() 即使在互斥锁下也会导致 print() python 函数的控制台输出无效

Posted

技术标签:

【中文标题】os.system() 即使在互斥锁下也会导致 print() python 函数的控制台输出无效【英文标题】:os.system() leads to invalid console output of print() python function even under mutex 【发布时间】:2021-09-17 07:25:27 【问题描述】:

我制作了一个脚本,它通过 ThreadPool 中的os.system() 调用一些程序并将工作结果打印到控制台。简化后的代码是这样的:

import os
from concurrent.futures import ThreadPoolExecutor, as_completed
import multiprocessing
from threading import Lock

print_mutex = Lock()
def print_safe(text):
    with print_mutex:
        print(text, flush=True)

def print_smth():
    res = os.system("")
    print_safe("1")

with ThreadPoolExecutor(max_workers = multiprocessing.cpu_count()) as thread_pool:
    future_results = [thread_pool.submit(print_smth) for i in range(40)]

    for future in future_results:
        future.result()

但是在控制台输出中我收到了这样的意外结果:

如果我评论res = os.system("") call,则输出有效。

为什么 os.system() 会以这种方式影响打印功能?

实施流程调用以避免此类问题的正确方法是什么?

【问题讨论】:

你是真实的(非简化的)子进程打印的东西吗? 我无法使用os.system("") 重现此内容。 我确实可以在 Windows 上重现 @o11c 没关系。我在简化示例中尝试了这两个选项并得到了相同的行为。我在 cmd 中在 Windows 10 上的 python 3.8.2 上运行了示例 即使在os.system("") 的情况下,该问题也是可重现的,因此没有输出。 【参考方案1】:

发生了什么:

Threadpool 创建一个并行工作的线程池。但是,您的主线程仍然是单线程。如果您的作业不需要时间(小于循环调用函数本身的周期),它将在调用下一个函数所需的时间内完成,它将显示为同步的。

os.system 在你的电脑上花费了一些时间(这可能会根据速度、操作系统和 CPU 数量而变化),因此线程同时结束,并且由于调用 os.system 的工作延迟,它们正在彼此相邻打印,因为它们在主应用程序的同一个单线程循环中打印(打印到控制台的那个)。

如果您的函数确实有效,您会看到预期的结果。

【讨论】:

所以你建议一些解决方法来隐藏问题? 我的建议是它应该正常工作。您不应该依赖 print 函数来测试异步。相反,您应该依赖完整的操作时间。

以上是关于os.system() 即使在互斥锁下也会导致 print() python 函数的控制台输出无效的主要内容,如果未能解决你的问题,请参考以下文章

为什么用cycle()创建的迭代器中的可变值没有更新,即使有停止条件,也会导致无限循环?

环境搭建-Redis

即使在 C# 代码中处理,InvalidOperationException 也会导致 Visual Studio 中断

在 os.system() 期间,啥会导致“IOError: [Errno 9] Bad file descriptor”?

CALayer 帧值即使在从超级层中移除后也会导致动画

11_Redis集群