2014-11-05 53 views
0

我正在編寫一些代碼,可以將日誌輸出到屏幕或文件,但不能同時輸出。 我認爲這樣做是寫一個類最簡單的方法:將Python輸出寫入屏幕或文件名

class WriteLog: 
    "write to screen or to file" 

    def __init__(self, stdout, filename): 
     self.stdout = stdout 
     self.logfile = file(filename, 'a') 

    def write(self, text): 
     self.stdout.write(text) 
     self.logfile.write(text) 

    def close(self): 
     self.stdout.close() 
     self.logfile.close() 

然後調用它是這樣的:

output = WriteLog(sys.stdout, 'log.txt') 

但是,我不知道如何讓切換這兩者之間應該有一個選項,它將設置WriteLog以使用stdout或filename。一旦設置了該選項,我只需使用WriteLog而不需要任何if報表等。

任何想法?我在網上看到的大多數解決方案都試圖同時輸出到兩者。

謝謝。

回答

1

也許這樣?它在構造函數中使用符號名稱'stdout''stderr',或使用真實文件名。 if的使用僅限於構造函數。順便說一句,我認爲你試圖過早地優化(這是所有邪惡的根源):你正試圖節省if的時間,而在現實生活中,該程序將花費更多的時間在文件I/O;使您的if的可能浪費可以忽略不計。

import sys 

class WriteLog: 

    def __init__(self, output): 
     self.output = output 
     if output == 'stdout': 
      self.logfile = sys.stdout 
     elif output == 'stderr': 
      self.logfile = sys.stderr 
     else: 
      self.logfile = open(output, 'a') 

    def write(self, text): 
     self.logfile.write(text) 

    def close(self): 
     if self.output != 'stdout' and self.output != 'stderr': 
      self.logfile.close() 

    def __del__(self): 
     self.close() 

if __name__ == '__main__': 
    a = WriteLog('stdout') 
    a.write('This goes to stdout\n') 
    b = WriteLog('stderr') 
    b.write('This goes to stderr\n') 
    c = WriteLog('/tmp/logfile') 
    c.write('This goes to /tmp/logfile\n') 
+0

這很好用!謝謝。我會嘗試擁抱'if'語句;) – mdhoney 2014-11-07 01:27:26

1

我不是專家,但嘗試使用logging library,也許你可以有2個處理程序的記錄器,一個用於文件,一個用於流,然後動態添加/刪除處理程序。

0

我喜歡關於使用日誌記錄庫的建議。但是如果你想自己破解一些東西,那麼傳遞文件句柄值得考慮。

import sys 

class WriteLog: 
    "write to screen or to file" 

    def __init__(self, output): 
     self.output = output 

    def write(self, text): 
     self.output.write(text) 

    def close(self): 
     self.output.close() 

logger = WriteLog(file('c:/temp/log.txt','a')) 
logger.write("I write to the log file.\n") 
logger.close() 

sysout = WriteLog(sys.stdout) 
sysout.write("I write to the screen.\n")   
+0

謝謝。結束了與卡雷爾稍微更廣泛的實施,但這是我一直在尋找。欣賞你的時間。 – mdhoney 2014-11-07 01:31:06

0

您可以使用logging庫來做類似的事情。以下函數將在INFO級別設置日誌記錄對象。

def setup_logging(file_name, log_to_file=False, log_to_console=False): 
    logger = logging.getLogger() 
    logger.setLevel(logging.DEBUG) 

    # Create Console handler 
    if log_to_file: 
     console_log = logging.StreamHandler() 
     console_log.setLevel(logging.INFO) 
     formatter = logging.Formatter('%(asctime)s - %(levelname)-8s - %(name)-12s - %(message)s') 
     console_log.setFormatter(formatter) 
     logger.addHandler(console_log) 

    # Log file 
    if log_to_console: 
     file_log = logging.FileHandler('%s.log' % (file_name), 'a', encoding='UTF-8') 
     file_log.setLevel(logging.INFO) 
     formatter = logging.Formatter('%(asctime)s - %(levelname)-8s - %(name)-12s - %(message)s') 
     file_log.setFormatter(formatter) 
     logger.addHandler(file_log) 

    return logger 

您將日誌的名稱以及您希望記錄的位置(文件,控制檯或兩者)傳遞給它。然後,你可以利用你的代碼塊這個功能是這樣的:

logger = setup_logging("mylog.log", log_to_file=True, log_to_console=False) 
logger.info('Message') 

這個例子將記錄到一個名爲mylog.log(當前目錄)文件,並有一個像這樣的輸出:

2014-11-05 17:20:29,933 - INFO  - root   - Message 

此功能有改進的地方(如果你想添加更多的功能)。現在,它在日誌級別INFO上的.setLevel(logging.INFO)行上登錄到控制檯和文件。如果您願意,可以動態設置。

此外,現在,您可以輕鬆添加標準日誌行(logger.debug('Message'),logger.critcal('DANGER!'))而無需修改類。在這些例子中,調試信息將不會被打印(因爲它被設置爲INFO),而關鍵的信息將會被打印。

+0

謝謝安迪。我知道'logging'庫,但在這種情況下,我想嘗試自己推出。感謝您的詳細示例! – mdhoney 2014-11-07 01:29:28