Shell

在後台執行 python 腳本後打開互動式 python shell

  • August 20, 2019

python3 -i test.py執行 test.py 後打開一個互動式 python shell。但是,如果我嘗試在後台執行它,python3 -i test.py & 作業會自動停止^C並顯示

[4]+  Stopped                 python3 -i test.py

,之後我無法訪問python的互動式shell(test.py中的變數仍在環境中)。fg執行該過程(即fg %4)會導致一個互動式 shell,在該 shell 中我的輸入無法看到,但在按下 後仍會執行<Enter>。在後台執行 test.py 後,如何“正常”執行互動式 shell?

(供參考,test.py 包含

from time import sleep
a = 'hello world'
for i in range(10):
   sleep(1)
   print(a)

我的外殼看起來像這樣:

$ python3 -i test.py &
[4] 6708
$ hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
fg %4
python3 -i test.py
>>> 'hello world'
>>>

a在第一個提示後輸入了>>>,但沒有顯示。)

  • 編輯@muru -

在 fg 中正常執行後將其發送到 bg 會得到:

$
$
$ python3 -i test.py
hello world
hello world
hello world
hello world
^Z
[4]+  Stopped                 python3 -i test.py
$ bg %4
[4]+ python3 -i test.py &
$ hello world
hello world
hello world
hello world
hello world
hello world
echo 'hello world'
hello world

[4]+  Stopped                 python3 -i test.py
$
$

shell 期待輸入的地方,我echo 'hello world'在 10 個“Hello World”之後輸入。

發生這種情況是因為後台的 Python 解釋器在執行完test.py程序後立即與命令行 shell “競爭”提示。

Python 自然會輸掉這場“戰鬥”,因為當時它不允許進行互動。然而,它停止得太晚了,足以讓自己的提示處於無法完全恢復fg命令的狀態。

解決此問題的一種方法是在 Python 程序的末尾添加以下行:

import os, signal  # access os-level functions and UNIX-signals
os.kill(os.getpid(), signal.SIGSTOP)  # send myself the UNIX SIGSTOP signal

(當然,import也可以按照典型做法將其放在您的程序之上。)

os.kill()行將使 Python 解釋器處於停止狀態,就像它在錯誤的時刻嘗試進行互動一樣。只是,這一次它自己做,甚至在嘗試提示之前,這樣它就不會處於不一致的狀態。

您知道何時os.kill()到達,因為命令行 shell 會通知您 Python 已停止。屆時將fg 恢復 Python,使其從os.kill()線路繼續,從而開始其自己的互動式會話。

不要bg在它被停止後恢復它os.kill(),因為這樣做只會使核心再次停止 Python 以嘗試在後台進行互動。

引用自:https://unix.stackexchange.com/questions/536119