2016-07-18 6 views
3

Я хочу получить доступ к трассировке программы python, запущенной в подпроцессе.subprocess child traceback

The documentation говорит:

Exceptions raised in the child process, before the new program has started to execute, will be re-raised in the parent. Additionally, the exception object will have one extra attribute called child_traceback, which is a string containing traceback information from the child’s point of view.

Содержание my_sub_program.py:

raise Exception("I am raised!") 

Содержание из my_main_program.py:

import sys 
import subprocess 
try: 
    subprocess.check_output([sys.executable, "my_sub_program.py"]) 
except Exception as e: 
    print e.child_traceback 

Если я бегу my_main_program.py, я получаю следующее сообщение об ошибке:

Traceback (most recent call last): 
    File "my_main_program.py", line 6, in <module> 
    print e.child_traceback 
AttributeError: 'CalledProcessError' object has no attribute 'child_traceback' 

Как получить доступ к трассировке подпроцесса без изменения кода программы подпроцесса? Это означает, что я хочу избежать добавления большого предложения try/except вокруг всего моего подпрограммного кода, но, скорее, обработать регистрацию ошибок из моей основной программы.

Редактировать:sys.executable следует заменить на переводчик, отличный от того, на котором работает основная программа.

+0

Doc говорит «перед тем, как новая программа запустилась», в вашем случае исключение было поднято во время выполнения новой программы, поэтому нет «child_traceback». После запуска новой программы вам нужно поймать исключение «CalledProcessError» и выполнить следующие действия: http://stackoverflow.com/questions/24849998/how-to-catch-exception-output-from-python-subprocess-check -output с использованием 'CalledProcessError.output' – mguijarr

+0

В моем примере' CalledProcessError.output' выполнил только стандартный вывод, но не отслеживал исключение. – schreon

+0

Это, вероятно, потому, что вывод отправляется на 'stderr'. Посмотрите ответы на вопрос, который я выслал вам по ссылке выше, для получения более подробной информации. – mguijarr

ответ

0

Когда вы начинаете новый процесс Python, вы также можете попытаться использовать модуль Python multiprocessing; по суб-причислять в Process класс довольно легко получить исключения из целевой функции:

from multiprocessing import Process, Pipe 
import traceback 
import functools 

class MyProcess(Process): 
    def __init__(self, *args, **kwargs): 
     Process.__init__(self, *args, **kwargs) 
     self._pconn, self._cconn = Pipe() 
     self._exception = None 

    def run(self): 
     try: 
      Process.run(self) 
      self._cconn.send(None) 
     except Exception as e: 
      tb = traceback.format_exc() 
      self._cconn.send((e, tb)) 
      # raise e # You can still rise this exception if you need to 

    @property 
    def exception(self): 
     if self._pconn.poll(): 
      self._exception = self._pconn.recv() 
     return self._exception 


p = MyProcess(target=functools.partial(execfile, "my_sub_program.py")) 
p.start() 
p.join() #wait for sub-process to end 

if p.exception: 
    error, traceback = p.exception 
    print 'you got', traceback 

Хитрость заключается в том, чтобы иметь целевую функцию, выполняющий эту подпрограмму Python, это делается с помощью functools.partial.

+0

Предоставляет ли это решение подпроцесс работать в другом интерпретаторе, чем основная программа? Поскольку я вижу ваше предложение, я замечаю, что в моем примере вводить в заблуждение использование 'sys.executable'. Однако в контексте моего вопроса мне нужно запустить скрипты в другой виртуальной среде, чем основной процесс. (основным процессом будет какой-то планировщик) – schreon

+0

Фактически «многопроцессорная обработка» делает «os.fork» на платформах POSIX, поэтому это не новая виртуальная среда; однако вы можете ограничить количество общих данных между процессами, запустив объекты «Process» на ранней стадии, это, возможно, достаточно справедливо для ваших нужд. – mguijarr

+0

Если вы делаете своего рода планировщик, почему бы не использовать что-то вроде [Сельдерей] (http://www.celeryproject.org/) – mguijarr