繁体   English   中英

当使用subprocess.call()时,如果使用非必需配置进行日志记录,如何设置它以将stdout重定向到日志文件的方式?

[英]When using subprocess.call(), how to set it in way that redirects stdout to a log file if you are using the disctionary configuration for logging?

我试图用Python重写此批处理行:

mkdir %TEMP%\FW >> %LOGDETAILS% 2>&1

使用subprocess.call()时,如果使用字典配置进行日志记录,如何以将stdout重定向到日志文件的方式进行设置?

到目前为止,我的Python代码看起来像这样(这只是其中一部分):

    DICT_CONFIG = {#I have my settings in here}
    logging.config.dictConfig(DICT_CONFIG)
    logdetails = logging.getLogger('SikuliScriptDetails_Logger')

    def my_function():
        logdetails.info("---------Benginning Tests--------------")
        #Set Project Name, Disable Feedback Dialogs by setting launches to 41
        returncode = subprocess.call(["regedit", "-s", "MainFolder/FwSetup.reg"], stderr = STDOUT, stdout = logdetails)

在准备好其他一些模块之前,我无法在相当长的一段时间内测试我的程序。 但是我的重定向尝试正确吗? 这样是否可以将["regedit", "-s", "MainFolder/FwSetup.reg"]记录到logdetails文件记录器中?

我是否有必要像将stdout发送到logdetails文件记录器之前一样先执行stderr = STDOUT

另外,有人知道41是什么意思吗? 我不知道该怎么办。

PS:我已经看过这个了,但是我仍然不明白,因为他们没有使用字典配置进行日志记录。

更新:PS:我也查看了此信息以了解代码的批处理行。

UPDATE2:对不起,我在开始时给您错误的代码行。 我应该在此处粘贴的批处理文件是:

"regedit", "-s", "VBoxScripts/FwSetup.reg"

不是这个: mkdir %TEMP%\\FW >> %LOGDETAILS% 2>&1谢谢。

您的问题有点困惑。


首先,有logging位。 使用哪种机制配置日志记录并不重要。 最后,您仍然会得到使用相同方法的Logger对象。 您正在做的事情似乎很合理,尽管使用'SikuliScriptDetails_Logger'作为记录器的名称'SikuliScriptDetails_Logger'


接下来,是这样的:

我是否有必要像将stdout发送到logdetails文件记录器之前一样先执行stderr = STDOUT?

文档所述 ,设置stderr=STDOUT意味着:

…应该将子进程中的stderr数据捕获到与stdout相同的文件句柄中。

换句话说,如果您想将stdout和stderr一起登录,则可以,您确实需要这样做。 如果您只想记录stdout或stderr,或者分别记录它们,那么不,您不应该这样做。

在批处理行中,听起来您确实想将stdout和stderr混合在一起,在这种情况下,您做对了。


最后,您需要通过标准输出。 从同一文档中:

有效值为PIPE,DEVNULL,现有文件描述符(正整数),现有文件对象和无。

特别是,您不能给它一个Logger对象。 您必须给它一个文件对象或PIPE

如果只希望将stdout和stderr附加到记录器正在使用的同一文件中,则可以获取记录器的文件对象并将其传递。 但是,一种更简单的方法是不首先使用logging -只需open文件,向其中write标头,然后将其作为stdout参数传递。 例如:

with open(log_details_path, 'a') as logfile:
    logfile.write("---------Benginning Tests--------------\n")
    returncode = subprocess.call(["regedit", "-s", "MainFolder/FwSetup.reg"], stdout=logfile, stderr=STDOUT)

但是,假设您首先使用logging ,这听起来像您真正想要的是这样:读取stderr的每一行,并将其记录为单独的日志消息。 如果是这样,则需要使用PIPE 如果您需要将其连续流式传输到日志中(例如,这将花费很长时间,发送大量数据,中间可能会失败……),则需要从PIPE显式read ,然后记录下您要记录的内容得到。 但是,如果没有,则可以仅使用communicate甚至check_output 例如:

child_output = subprocess.check_output(["regedit", "-s", "MainFolder/FwSetup.reg"], stderr = STDOUT)
for line in child_output.splitlines():
    logdetails.info(line)

它很容易将输出重定向到文件,更难通过日志记录模块完成。 假设您真正想要的只是将stdout和stderr传递到文件的python等效项,则可以执行以下操作:

log_details = "SikuliScriptDetails.log"
returncode = subprocess.call(
    ["regedit", "-s", "MainFolder/FwSetup.reg"],
    stdout=open(log_details, 'a'), 
    stderr=subprocess.STDOUT)

如果您担心文件关闭,可以使用with子句:

log_details = "SikuliScriptDetails.log"
with open(log_details, 'a') as log_fp:
    returncode = subprocess.call(
        ["regedit", "-s", "MainFolder/FwSetup.reg"],
        stdout=log_fp, 
        stderr=subprocess.STDOUT)

如果要将stdout记录为info并将stderr记录为warn,则可以使用线程:

import threading
import subprocess

def log_thread(pipe, logger):
    for line in pipe:
        logger(line.strip())

def my_call(logger, cmd, **kw):
    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
        **kw)
    stdout = threading.Thread(target=log_thread, args=(proc.stdout, logger.info))
    stdout.start()
    stderr = threading.Thread(target=log_thread, args=(proc.stderr, logger.warn))
    stderr.start()
    stdout.join()
    stderr.join()
    return proc.wait()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM