[英]How to read from stdin or from a file if no data is piped in Python?
我有一個 CLI 腳本並希望它從文件中讀取數據。 它應該能夠以兩種方式閱讀它:
cat data.txt | ./my_script.py
./my_script.py data.txt
——有點像grep
,例如。
我知道的:
sys.argv
和optparse
讓我可以輕松閱讀任何參數和選項。sys.stdin
讓我讀取管道輸入的數據fileinput
使整個過程自動化很遺憾:
fileinput
使用 stdin 和任何 args 作為輸入。 所以我不能使用不是文件名的選項,因為它試圖打開它們。sys.stdin.readlines()
工作正常,但如果我不通過管道傳輸任何數據,它會掛起,直到我輸入Ctrl + Dstdin
在布爾上下文中始終為True
。如果可能的話,我想要一種便攜的方式來做到這一點。
Argparse允許以相當簡單的方式完成此操作,除非您有兼容性問題,否則您確實應該使用它而不是optparse
。
代碼將是這樣的:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--input', type = argparse.FileType('r'), default = '-')
現在你有一個解析器來解析你的命令行參數,如果它看到一個文件就使用一個文件,如果沒有則使用標准輸入。
按照您的fileinput.input()
處理非文件名參數,因此您會得到一個非選項參數數組,然后將該數組作為參數傳遞給fileinput.input()
:
import fileinput
for line in fileinput.input(remaining_args):
process(line)
對於 unix/linux,您可以通過查看os.isatty(0)
來檢測是否正在通過管道傳輸數據
$ date | python -c "import os;print os.isatty(0)"
False
$ python -c "import os;print os.isatty(0)"
True
我不確定 Windows 是否有等價物。
編輯好的,我在 windows XP 上用 python2.6 試過了
C:\Python26>echo "hello" | python.exe -c "import os;print os.isatty(0)"
False
C:\Python26> python.exe -c "import os;print os.isatty(0)"
True
因此,對於 Windows 而言,也許並非完全沒有希望
我是一個菜鳥,所以這可能不是一個好的答案,但我正在嘗試做同樣的事情(在命令行上允許一個或多個文件,否則默認為 STDIN)。
我放在一起的最終組合:
parser = argparse.ArgumentParser()
parser.add_argument("infiles", nargs="*")
args = parser.parse_args()
for line in fileinput.input(args.infiles):
process(line)
這似乎是在一個優雅的包中獲得所有所需行為的唯一方法,而無需命名參數。 就像使用 unix 命令一樣:
cat file1 file2
wc -l < file1
不是:
cat --file file1 --file file2
非常感謝經驗豐富的慣用 Pythonistas 的反饋/確認,以確保我得到了最好的答案。 沒有在其他任何地方看到這個完整的解決方案,只是片段。
沒有可靠的方法來檢測sys.stdin
是否連接到任何東西,這樣做也不合適(例如,用戶想要粘貼數據)。 檢測文件名是否存在作為參數,如果沒有找到則使用 stdin。
您可以使用此函數來檢測輸入是否來自管道。
sys.stdin.isatty()
如果輸入來自管道,則返回 false,否則返回 true。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.