使用python多处理和curses,终止进程似乎会干扰curses显示。
例如,在下面的代码中,为什么终止进程会阻止curses显示文本? (按a后按b)
更准确地说,似乎不仅字符串“hello”不再显示,而且整个curses窗口也不再显示。
import curses
from multiprocessing import Process
from time import sleep
def display(stdscr):
stdscr.clear()
curses.newwin(0,0)
stdscr.timeout(500)
p = None
while True:
stdscr.addstr(1, 1, "hello")
stdscr.refresh()
key = stdscr.getch()
if key == ord('a') and not p:
p = Process(target = hang)
p.start()
elif key == ord('b') and p:
p.terminate()
def hang():
sleep(100)
if __name__ == '__main__':
curses.wrapper(display)
我在 GNU/Linux 下运行 python 3.6。
编辑:
我仍然能够使用这个不调用 sleep() 的更精简的版本进行重现。现在只需按“a”就会触发该错误。
import curses
from multiprocessing import Process
def display(stdscr):
stdscr.clear()
curses.newwin(0,0)
stdscr.timeout(500)
p = None
while True:
stdscr.addstr(1, 1, "hello")
stdscr.refresh()
key = stdscr.getch()
if key == ord('a') and not p:
p = Process(target = hang)
p.start()
p.terminate()
def hang():
while True:
temp = 1 + 1
if __name__ == '__main__':
curses.wrapper(display)
最佳答案
以下代码有效:
import curses
from multiprocessing import Process
p = None
def display(stdscr):
stdscr.clear()
curses.newwin(0,0)
stdscr.timeout(500)
while True:
stdscr.addstr(1, 1, "hello")
stdscr.refresh()
key = stdscr.getch()
if key == ord('a') and not p:
p.start()
p.terminate()
def hang():
while True:
temp = 1 + 1
if __name__ == '__main__':
p = Process(target = hang)
curses.wrapper(display)
我创建了一个新的Process
在使用 curses.wrapper()
初始化 UI 之前。好吧,为什么这有效?为此我们必须知道如何Proccess工作原理以及当您调用 Process(target = hang)
时它到底做了什么:
fork
The parent process uses os.fork() to fork the Python interpreter. The child process, when it begins, is effectively identical to the parent process. All resources of the parent are inherited by the child process. Note that safely forking a multithreaded process is problematic.
Available on Unix only. The default on Unix.
现在,它告诉我们什么?你在哪里创建一个新的Processes
当您已经创建了 curses
屏幕。 curses.wrapper() 是什么意思?做什么?
Before calling func, wrapper() turns on cbreak mode, turns off echo, enables the terminal keypad, and initializes colors if the terminal has color support. On exit (whether normally or by exception) it restores cooked mode, turns on echo, and disables the terminal keypad.
好的,我们有一个新创建的子进程,它拥有与其父进程完全相同的资源。当您调用terminate()
时为了杀死 child ,它会释放所有资源,包括诅咒包装器。它会恢复之前的终端设置,从而破坏您的 UI。
要解决此问题,您必须以不同的方式实现您的程序。事先创建一个新进程,使用IPC要与您的进程通信,请使用 Process Pools如果您需要多个进程,Threading或Thread Pools如果您有 IO 绑定(bind)任务。
关于python - 终止进程会打破Python的诅咒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44677774/