简体   繁体   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?

I am trying to rewrite this batch line in Python: 我试图用Python重写此批处理行:

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

When using subprocess.call(), how to set it in way that redirects stdout to a log file if you are using the dictionary configuration for logging? 使用subprocess.call()时,如果使用字典配置进行日志记录,如何以将stdout重定向到日志文件的方式进行设置?

My Python code looks like this so far (this is just part of it): 到目前为止,我的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)

I can not test my program for quite a while until I have some other modules ready. 在准备好其他一些模块之前,我无法在相当长的一段时间内测试我的程序。 But is my attempt at redirection correct? 但是我的重定向尝试正确吗? Is this going to be able to log the output of the ["regedit", "-s", "MainFolder/FwSetup.reg"] into my logdetails file logger? 这样是否可以将["regedit", "-s", "MainFolder/FwSetup.reg"]记录到logdetails文件记录器中?

Is it necessary for me to do stderr = STDOUT first like I did before sending stdout to logdetails file logger? 我是否有必要像将stdout发送到logdetails文件记录器之前一样先执行stderr = STDOUT

Also, does anyone know what the 41 means? 另外,有人知道41是什么意思吗? I do not know what to do with it. 我不知道该怎么办。

PS: I've looked at this already, but I still don't get it since they are not using dictionary configuration for logging. PS:我已经看过这个了,但是我仍然不明白,因为他们没有使用字典配置进行日志记录。

UPDATE: PS: I've also looked at this information to understand the batch line of code. 更新:PS:我也查看了此信息以了解代码的批处理行。

UPDATE2: Sorry, I gave you the wrong line of code at the beginning. UPDATE2:对不起,我在开始时给您错误的代码行。 The batch file I was supposed to give paste here is: 我应该在此处粘贴的批处理文件是:

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

not this one: mkdir %TEMP%\\FW >> %LOGDETAILS% 2>&1 Thanks. 不是这个: mkdir %TEMP%\\FW >> %LOGDETAILS% 2>&1谢谢。

Your question is a bit confused. 您的问题有点困惑。


First, there's the logging bit. 首先,有logging位。 It doesn't matter which mechanism you use for configuring logging; 使用哪种机制配置日志记录并不重要。 in the end, you still end up with a Logger object with the same methods. 最后,您仍然会得到使用相同方法的Logger对象。 What you're doing seems reasonable, although it is a bit weird to use 'SikuliScriptDetails_Logger' as a name for a logger. 您正在做的事情似乎很合理,尽管使用'SikuliScriptDetails_Logger'作为记录器的名称'SikuliScriptDetails_Logger'


Next, there's this: 接下来,是这样的:

Is it necessary for me to do stderr = STDOUT first like I did before sending stdout to logdetails file logger? 我是否有必要像将stdout发送到logdetails文件记录器之前一样先执行stderr = STDOUT?

Setting stderr=STDOUT means, as the docs explain: 文档所述 ,设置stderr=STDOUT意味着:

… that the stderr data from the child process should be captured into the same file handle as for stdout. …应该将子进程中的stderr数据捕获到与stdout相同的文件句柄中。

In other words, if you want to log stdout and stderr together, then yes, you do need to do this; 换句话说,如果您想将stdout和stderr一起登录,则可以,您确实需要这样做。 if you want to log just stdout, or just stderr, or to log them each separately, then no, you should not do this. 如果您只想记录stdout或stderr,或者分别记录它们,那么不,您不应该这样做。

From your batch line, it sounds like you do want to mix stdout and stderr together, in which case you're doing the right thing. 在批处理行中,听起来您确实想将stdout和stderr混合在一起,在这种情况下,您做对了。


Finally, there's what you pass for stdout. 最后,您需要通过标准输出。 From the same documentation: 从同一文档中:

Valid values are PIPE, DEVNULL, an existing file descriptor (a positive integer), an existing file object, and None. 有效值为PIPE,DEVNULL,现有文件描述符(正整数),现有文件对象和无。

In particular, you cannot give it a Logger object; 特别是,您不能给它一个Logger对象。 you have to give it a file object or PIPE . 您必须给它一个文件对象或PIPE

If you just want it to append stdout and stderr to the same file the logger is using, you can get the logger's file object and pass that. 如果只希望将stdout和stderr附加到记录器正在使用的同一文件中,则可以获取记录器的文件对象并将其传递。 However, a much simpler way to do it would be to not use logging in the first place—just open a file, write the header to that, and pass it as the stdout parameter. 但是,一种更简单的方法是不首先使用logging -只需open文件,向其中write标头,然后将其作为stdout参数传递。 For example: 例如:

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)

But, given that you're using logging in the first place, it sounds like what you really want is something like this: read each line of stderr, and log it as a separate log message. 但是,假设您首先使用logging ,这听起来像您真正想要的是这样:读取stderr的每一行,并将其记录为单独的日志消息。 If so, you need to use a PIPE . 如果是这样,则需要使用PIPE If you need to stream it continuously to the log (eg, it's going to take a long time, send a lot of data, possibly fail in the middle…), you'll need to explicitly read from the PIPE and then log what you get. 如果您需要将其连续流式传输到日志中(例如,这将花费很长时间,发送大量数据,中间可能会失败……),则需要从PIPE显式read ,然后记录下您要记录的内容得到。 But if not, you can just use communicate , or even check_output . 但是,如果没有,则可以仅使用communicate甚至check_output For example: 例如:

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

Its easy to redirect output to a file, harder to do it through the logging module. 它很容易将输出重定向到文件,更难通过日志记录模块完成。 Assuming that all you really want is the python equivalent of piping stdout and stderr to a file, you can do: 假设您真正想要的只是将stdout和stderr传递到文件的python等效项,则可以执行以下操作:

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

You can use a with clause if you worry about the file closing: 如果您担心文件关闭,可以使用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)

If you want to log stdout as info and stderr as warn, you can use threads: 如果要将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