簡體   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