2017-10-19 240 views
1

我想寫一個Python腳本,它允許用戶在標準輸入/標準輸出和輸入/輸出文件之間切換。但我不知道如果我的實現是正確的:如何抽象stdin/stdout和文件?

#!/usr/bin/python3 

import fileinput 
import sys 

from contextlib import contextmanager 
from contextlib import redirect_stdout 


def foo(file): 
    return ''.join([line for line in file]) 


@contextmanager 
def run(input_file, output_file): 
    stdin = '-' if input_file is None else input_file 
    stdout = sys.stdout if output_file is None else open(output_file, 'w') 
    with fileinput.input(stdin) as stdin, stdout: 
     with redirect_stdout(stdout): 
      print(foo(stdin)) 
  1. 是代碼管理資源是否正確?
  2. 如何正確處理字符編碼?我想在utf-8中擁有一切。
  3. 上述代碼有沒有改進的餘地?

回答

1

我認爲你需要這樣做。你不需要使run()本身成爲@contextmanager-所有它需要做的就是使用一個(或更多,fileinput.inputredirect_stdout已經是)。我不知道你爲什麼使用fileinput.input,因爲似乎只涉及一個輸入文件。

from contextlib import redirect_stdout 
import fileinput 
import sys 

def foo(file): 
    return ''.join([line for line in file]) 

def run(input_file, output_file): 
    stdin = '-' if input_file is None else input_file 
    stdout = sys.stdout if output_file is None else open(output_file, 'w') 
    with fileinput.input(stdin) as stdin, redirect_stdout(stdout): 
     print(foo(stdin)) 

run('input.txt', 'output.txt') 
run('input.txt', None) 
+0

感謝您的信息。我正在使用'fileinput',因爲可能有多個輸入文件。主要目標是使腳本可管。我不確定我瞭解你對「@ contextmanager」的評論。你是否正在用目前的實現來說,我不需要'@ contextmanager'?還請你對字符編碼進行評論? – Rad

+0

我的意思是說,因爲'fileinput.input()'和'redirect_stdout()'既是上下文管理器,也沒有必要讓'run()'也是。至於編碼方面,如果'stdout'沒有被重定向,你可能會遇到一個問題,這取決於'sys.stdout'的默認編碼是用於你的操作系統的。對於文件,您可能必須使用['codecs.open()'](https://docs.python.org/3/library/codecs.html#codecs.open)以避免在讀取和寫入數據時出現編碼問題/取決於它們包含的內容。爲什麼不嘗試運行它並看看,而不是在這裏提出假設性問題。 – martineau