从终端解耦的过程仍然输出 Traceback 到终端

Decoupled process from terminal still outputs Traceback to the terminal

在测试我使用 rest 创建的应用程序时 api 我发现了这种我不理解的行为。
让我们首先重现类似的错误,如下所示 -
在文件 call.py -
请注意 该文件包含可以直观地显示自身的代码,例如一个 运行 永远存在的 GUI。在这里,我只是向您展示一个表示,并故意让它引发一个异常来向您展示问题。发出获取请求然后尝试将结果解析为 json 将引发 JSONDecodeError.

import requests
from time import sleep

sleep(3)
uri = 'https://google.com'
r = requests.get(uri)
response_dict = r.json()

因为我想 运行 这是一个守护进程,所以我使用以下技巧将这个进程与启动它的终端分离 -
在文件中 start.py -

import subprocess
import sys

subprocess.Popen(["python3", "call.py"])
sys.exit(0)

然后我执行python3 start.py
显然 解耦了过程,因为如果没有例外,视觉表现 运行 是完美的。
但是,如果出现异常,我会立即在终端中看到此输出,即使我在调用 python3 start.py -

后收到了新提示
$ python3 start.py
$ Traceback (most recent call last):
  File "call.py", line 7, in <module>
    response_dict = r.json()
  File "/home/walker/.local/lib/python3.6/site-packages/requests/models.py", line 896, in json
    return complexjson.loads(self.text, **kwargs)
  File "/usr/lib/python3/dist-packages/simplejson/__init__.py", line 518, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3/dist-packages/simplejson/decoder.py", line 370, in decode
    obj, end = self.raw_decode(s)
  File "/usr/lib/python3/dist-packages/simplejson/decoder.py", line 400, in raw_decode
    return self.scan_once(s, idx=_w(s, idx).end())
simplejson.errors.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

现在,我了解到所有异常都必须在程序本身中处理。在这个奇怪的问题之后我已经这样做了,但我不清楚的是 为什么首先会发生这种情况?
如果我退出终端并重新启动终端,则不会发生这种情况(在回溯的情况下,视觉表现会卡住,并且不会像预期的那样在任何终端上输出)
为什么解耦过程会这样?
注意:解耦对我来说是势在必行的。必须将 GUI 运行 作为后台或守护进程,并且从中释放它的终端。

通过“解耦”,我假设您的意思是您希望 stdout/stderr 转到 /dev/null?假设这就是你的意思,那不是你告诉你的代码要做的

来自 docs:

stdin, stdout and stderr specify the executed program’s standard input, standard output and standard error file handles, respectively. Valid values are PIPE, DEVNULL, an existing file descriptor (a positive integer), an existing file object, and None.

With the default settings of None, no redirection will occur; the child’s file handles will be inherited from the parent.

因此您可能想要做的是:

from subprocess import Popen, DEVNULL

Popen(["python3", "call.py"], stdin=DEVNULL, stdout=DEVNULL, stderr=DEVNULL)

根据 OP 的评论,我认为他们可能在寻找像 GNU screentmux 这样的工具。像这样的终端多路复用器允许您创建一个虚拟终端,您可以在需要时断开连接并重新连接。这些答案见 https://askubuntu.com/a/220880/106239 and https://askubuntu.com/a/8657/106239 分别有 tmuxscreen 的例子