1

我正在尝试用 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 文件记录器中?

我是否有必要stderr = STDOUT像在将标准输出发送到 logdetails 文件记录器之前那样先做?

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

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

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

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

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

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

4

2 回答 2

0

将输出重定向到文件很容易,通过日志模块更难做到。假设您真正想要的只是将 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()
于 2013-08-05T20:30:37.897 回答
0

你的问题有点混乱。


首先,有logging一点。使用哪种机制来配置日志记录并不重要;最后,您仍然会得到一个Logger具有相同方法的对象。您所做的似乎是合理的,尽管'SikuliScriptDetails_Logger'用作记录器的名称有点奇怪。


接下来是这样的:

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

正如文档解释的那样,设置stderr=STDOUT意味着:

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

换句话说,如果您想将 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首先使用的是,听起来您真正想要的是这样的:读取标准错误的每一行,并将其记录为单独的日志消息。如果是这样,您需要使用PIPE. 如果您需要将其连续流式传输到日志(例如,这将花费很长时间,发送大量数据,可能在中间失败......),您需要显式地readPIPE然后记录您获得的内容。但如果没有,您可以只使用communicate, 甚至check_output. 例如:

child_output = subprocess.check_output(["regedit", "-s", "MainFolder/FwSetup.reg"], stderr = STDOUT)
for line in child_output.splitlines():
    logdetails.info(line)
于 2013-08-05T20:27:33.823 回答