Mat*_*ams 5 python subprocess stderr
我一直在尝试编写一个程序来记录子进程的未捕获异常和语法错误。容易,对吧?只需将管道输送stderr到正确的位置即可。
然而,子进程是另一个 python 程序——我称之为test.py——需要运行,就好像它的输出/错误没有被捕获一样。也就是说,运行记录器程序需要看起来就像用户刚刚python test.py正常运行一样。
使问题进一步复杂化的是如果不使用则实际发送到的问题。不幸的是,我不能,因为我无法控制使用错误记录器运行的文件。raw_inputstderrreadlineimport readline
笔记:
pexpect或编辑这些*customize.py文件(因为该程序将由许多不同的用户运行)。我真的觉得无论如何应该有一个 stdlib 解决方案......我尝试过以下方法,但没有成功:
tee问题中的如何在使用带有管道的“tee”时将 stderr 写入文件?(未能产生raw_input提示);我在几个 SO 问题中发现的python 实现也tee有类似的问题sys.excepthook(无法使其适用于子进程)raw_input正确显示提示。根据@nneonneo 在问题评论中的建议,我制作了这个程序,似乎可以完成工作。(请注意,目前,记录器文件的名称必须为“pylog”,才能将错误正确打印给最终用户。)
#!/usr/bin/python
'''
This module logs python errors.
'''
import socket, os, sys, traceback
def sendError(err):
# log the error (in my actual implementation, this sends the error to a database)
with open('log','w') as f:
f.write(err)
def exceptHandler(etype, value, tb):
"""An additional wrapper around our custom exception handler, to prevent errors in
this program from being seen by end users."""
try:
subProgExceptHandler(etype, value, tb)
except:
sys.stderr.write('Sorry, but there seems to have been an error in pylog itself. Please run your program using regular python.\n')
def subProgExceptHandler(etype, value, tb):
"""A custom exception handler that both prints error and traceback information in the standard
Python format, as well as logs it."""
import linecache
errorVerbatim = ''
# The following code mimics a traceback.print_exception(etype, value, tb) call.
if tb:
msg = "Traceback (most recent call last):\n"
sys.stderr.write(msg)
errorVerbatim += msg
# The following code is a modified version of the trackeback.print_tb implementation from
# cypthon 2.7.3
while tb is not None:
f = tb.tb_frame
lineno = tb.tb_lineno
co = f.f_code
filename = co.co_filename
name = co.co_name
# Filter out exceptions from pylog itself (eg. execfile).
if not "pylog" in filename:
msg = ' File "%s", line %d, in %s\n' % (filename, lineno, name)
sys.stderr.write(msg)
errorVerbatim += msg
linecache.checkcache(filename)
line = linecache.getline(filename, lineno, f.f_globals)
if line:
msg = ' ' + line.strip() + '\n'
sys.stderr.write(msg)
errorVerbatim += msg
tb = tb.tb_next
lines = traceback.format_exception_only(etype, value)
for line in lines:
sys.stderr.write(line)
errorVerbatim += line
# Send the error data to our database handler via sendError.
sendError(errorVerbatim)
def main():
"""Executes the program specified by the user in its own sandbox, then sends
the error to our database for logging and analysis."""
# Get the user's (sub)program to run.
try:
subProgName = sys.argv[1]
subProgArgs = sys.argv[3:]
except:
print 'USAGE: ./pylog FILENAME.py *ARGS'
sys.exit()
# Catch exceptions by overriding the system excepthook.
sys.excepthook = exceptHandler
# Sandbox user code exeuction to its own global namespace to prevent malicious code injection.
execfile(subProgName, {'__builtins__': __builtins__, '__name__': '__main__', '__file__': subProgName, '__doc__': None, '__package__': None})
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2452 次 |
| 最近记录: |