Отсоединенный процесс от терминала все еще выводит Traceback на терминал - PullRequest
0 голосов
/ 06 ноября 2018

При тестировании приложения, созданного с использованием 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)

Теперь я понимаю, что все исключения ДОЛЖНЫ обрабатываться в самой программе. И я сделал это после этой странной проблемы, но что мне не понятно, это , почему это вообще произошло вообще ?
Этого не произойдет, если я выйду из терминала и перезапущу терминал (визуальное проявление застревает в случае трассировки, и не выводится ни на один терминал, как ожидалось)
Почему разъединенный процесс ведет себя так?
ПРИМЕЧАНИЕ : для меня обязательна развязка. Крайне важно, чтобы графический интерфейс выполнялся как фоновый или демонический процесс, а терминал, который его порождает, освобождается от него.

1 Ответ

0 голосов
/ 07 ноября 2018

от "разъединенного", я полагаю, вы имеете в виду, что хотите, чтобы 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)

Основываясь на комментариях ОП, я думаю, что они могут быть за таким инструментом, как GNU screen или tmux. Терминальные мультиплексоры, подобные этим, позволяют вам создать виртуальный терминал, от которого вы можете отключиться и подключиться к нему при необходимости. эти ответы см. https://askubuntu.com/a/220880/106239 и https://askubuntu.com/a/8657/106239 имеют примеры для tmux и screen соответственно

...