Python 从终端分离的过程仍然向终端输出回溯

Python 从终端分离的过程仍然向终端输出回溯,python,terminal,process,subprocess,traceback,Python,Terminal,Process,Subprocess,Traceback,在测试我使用rest api制作的应用程序时,我发现了这种我不理解的行为。 让我们从如下重现类似错误开始- 在文件call.py- 注意此文件中的代码可以直观地显示自己,例如一个永远运行的GUI。在这里,我只是向你们展示一个陈述,故意让它提出一个例外,向你们展示这个问题。发出get请求,然后尝试将结果解析为json将引发JSONDecodeError import requests from time import sleep sleep(3) uri = 'https://google.co

在测试我使用rest api制作的应用程序时,我发现了这种我不理解的行为。
让我们从如下重现类似错误开始-
在文件
call.py
-
注意此文件中的代码可以直观地显示自己,例如一个永远运行的GUI。在这里,我只是向你们展示一个陈述,故意让它提出一个例外,向你们展示这个问题。发出get请求,然后尝试将结果解析为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
$ 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)
然后我执行
python3start.py

它显然将过程解耦,因为如果没有异常,视觉显示将完美运行。
但是,如果出现异常,我会立即在终端中看到此输出,即使在调用
python3start.py之后我得到了一个新的提示-

import subprocess
import sys

subprocess.Popen(["python3", "call.py"])
sys.exit(0)
$ 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)
$python3 start.py
$Traceback(最近一次呼叫最后一次):
文件“call.py”,第7行,在
response_dict=r.json()
json格式的文件“/home/walker/.local/lib/python3.6/site packages/requests/models.py”,第896行
返回complexjson.load(self.text,**kwargs)
文件“/usr/lib/python3/dist-packages/simplejson/_-init__.py”,第518行,装入
返回\u默认\u解码器。解码
文件“/usr/lib/python3/dist packages/simplejson/decoder.py”,第370行,在decode中
obj,end=self.raw_解码
文件“/usr/lib/python3/dist packages/simplejson/decoder.py”,第400行,原始解码
返回self.scan_一次(s,idx=_w(s,idx.end())
simplejson.errors.JSONDecodeError:预期值:第1行第1列(字符0)
现在,我明白了所有异常都必须在程序本身中处理。在这个奇怪的问题之后,我做了这件事,但我不清楚的是,为什么会发生这种事 如果我退出终端并重新启动终端,则不会发生这种情况(在回溯的情况下,视觉显示会卡住,并且任何终端上都没有预期的输出)
为什么一个解耦的进程会这样运行?
注意:脱钩对我来说是必不可少的。GUI必须作为后台进程或守护进程运行,并且生成它的终端必须从中释放。

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

从:

stdin、stdout和stderr分别指定执行程序的标准输入、标准输出和标准错误文件句柄。有效值包括
PIPE
DEVNULL
、现有文件描述符(正整数)、现有文件对象和
None

默认设置为
None
,则不会发生重定向;子级的文件句柄将从父级继承

因此,您可能想做:

from subprocess import Popen, DEVNULL

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

根据OPs的评论,我认为他们可能在寻找GNU
screen
tmux
等工具。像这样的终端多路复用器允许您创建一个虚拟终端,您可以在需要时断开连接并重新连接。这些答案分别有
tmux
screen
的示例

谢谢您的回答。你知道这是不是“解耦”的正确方法吗?我所说的“解耦”基本上是指启动流程的终端必须脱离流程(通常在流程完成之前或除非流程完成,否则我们不会得到新的提示,对吗?)。是否可以在同一个程序中执行此操作(不写
start.py
。我希望这样做,因为这是一个运行时间很长的诊断程序,基本上只要我的笔记本电脑还在运行就可以运行。@raj我已经根据这条评论更新了我的答案,希望我的解释正确!非常感谢,但实际上我已经浏览了很多关于
nohup
,“screen”等。它们的问题是它们是特定于平台的,并且(或)需要额外的安装。我的想法是,由于Python的库已经成熟,并且出现了诸如
子进程
线程
等模块,所以应该可以使用
Popen
完成我们正在做的事情,但不需要额外的脚本。我对
Popen
感到满意,这就是我所认为的这是一个更好的解决方案。我真的不想使用额外的工具来完成我们现在通过
Popen
所做的事情。GUI和后台进程的概念是非常特定于平台的;您曾经做过任何嵌入式开发吗?我会坚持使用我最初针对的操作系统的工具,并担心是否需要移植这很重要