【问题标题】:Decoupled process from terminal still outputs Traceback to the terminal从终端解耦的进程仍然输出 Traceback 到终端
【发布时间】:2019-04-10 06:42:32
【问题描述】:

在测试我使用 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
显然将过程解耦,因为如果没有例外,视觉表现就会完美运行。
但是,如果出现异常,我会立即在终端中看到此输出,即使我在调用 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)

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

【问题讨论】:

    标签: python terminal process subprocess traceback


    【解决方案1】:

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

    来自docs

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

    使用默认设置None,不会发生重定向;子文件句柄将从父文件继承。

    因此您可能想要这样做:

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

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

    【讨论】:

    • 感谢您的回答。您知道这是否是“解耦”的正确方法吗?通过“解耦”,我基本上是指启动进程的终端必须脱离进程(通常直到并且除非进程完成,否则我们不会得到新的提示,对吧?)。是否可以在同一个程序中执行此操作(不写start.py。我希望发生这种情况,因为这是一个运行时间很长的诊断程序,基本上只要我的笔记本电脑开机就运行。跨度>
    • @raj 我已根据此评论更新了我的答案,希望我的解释正确!
    • 非常感谢,但实际上我浏览了很多有关 nohup、'screen` 等工具的资源。它们的问题是它们是特定于平台的并且(或)需要额外安装。我的想法是,由于 Python 的库已经成熟,并且出现了 subprocessthreading 等模块,因此应该可以使用 Popen 来完成我们正在做的事情,但无需额外的脚本。我对Popen 很满意,只是我认为有更好的解决方案。我真的不想使用额外的工具来做我们现在 Popen 所做的事情。
    • GUI 和后台进程的概念是非常特定于平台的;你做过嵌入式开发吗?我会坚持使用最初针对的操作系统的工具,并担心如果/当它变得重要时移植
    猜你喜欢
    • 1970-01-01
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-05
    • 2013-08-18
    • 2020-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多