我在 Python 3.11 中编写了这个简单的代码来学习多处理模块:
from multiprocessing import Process
import time
def proc(text):
while True:
print(text)
time.sleep(1)
print(__name__)
if __name__ == '__main__':
p = Process(target=proc, args=('hi',))
p.start()
input('Press any key to exit')
p.terminate()
这个想法是让进程 p 继续打印文本,直到主进程调用 p.terminate()。
但是当我运行这段代码时,我得到的是:
进程 p 永远不会被调用。但是,如果我删除带有 input() 函数的行,程序将按预期运行:
为什么会发生这种情况?我怎样才能解决这个问题? 我在 Windows 10 中的 PyCharm IDE 中运行此代码。
任何将数据写入标准输出或标准错误流,或者从标准输入流获取数据的应用程序,都会与其正在执行的终端进行交互。
虽然这听起来可能很复杂,但这仅仅意味着如果您的脚本使用
print()
或 input()
,从用户的角度来看它的行为方式将取决于用户运行它的终端。终端有实际显示打印内容并收集用户输入。 (请注意,如果您使用直接与读取键盘输入的系统 API 交互的库,这会变得更加复杂,例如 keyboard
)
此终端可以是 Windows 控制台主机(Windows 10 早期及之前版本中命令提示符的默认设置)、Windows 终端(Windows 11 中 PowerShell 的默认设置),还可以是通过 SSH 在云上运行脚本的终端模拟器(例如,在某种终端仿真模式下运行,或者您的 Linux 发行版实现的任何终端。
当您从 IDE 执行脚本时,它可以实现自己的终端,该终端的工作方式可能与您在操作系统上习惯的终端略有不同。 PyCharm 就是一个很好的例子。即使您可能在 Windows 上运行它,其终端的行为也与 Windows 终端和 Windows 控制台主机不同。
如果您依赖终端以某种及时的方式响应,则使用终端输入和输出以及multiprocessing
的脚本可能会导致额外的混乱。您的脚本在 Windows 控制台主机和 Windows 终端上按预期运行,但在 PyCharm 的终端上不运行。在 PyCharm 中,您可以通过使用一些运行配置直接从 IDE 运行脚本来轻松看到这种差异。然后从“终端”提示符下再次运行它,例如
python myscript.py
。您会发现系统终端中的行为很好。(无关注解:你的输入提示说按“任意键”,但是
input()
只会在有人按 Enter/Return 时终止你的脚本,因为这样就完成了
input()
的输入收集)你无法真正“修复”这个问题,因为没有什么可以修复的——一切都按其应有的方式运行。但是,如果
input()
语句仅用于调试目的,则解决方案是使用等待用户输入而不依赖于正在运行的终端的库(如
keyboard
)。使用
pip install keyboard
或使用 UI 中的项目设置安装它,然后尝试以下操作:
from multiprocessing import Process
import time
from keyboard import read_key
def proc(text):
while True:
print(text)
time.sleep(1)
if __name__ == '__main__':
p = Process(target=proc, args=('hi',))
p.start()
print("Press any key to stop the process...")
read_key()
p.terminate()
请注意,当您按任意键时,这实际上会停止,并且在所有终端中的工作方式相同。