python3輸入 - python連續輸入




你如何從Python中的標準輸入讀取? (13)

我試圖做一些代碼高爾夫的挑戰,但他們都需要輸入來自stdin 。 我如何在Python中獲取?


你如何從Python的標準輸入讀取?

我試圖做一些代碼高爾夫的挑戰,但他們都需要輸入來自stdin。 我如何在Python中獲取?

您可以使用:

  • sys.stdin - 類似文件的對象 - 調用sys.stdin.read()來讀取所有內容。
  • input(prompt) - 傳遞一個可選的提示輸出,它從標準輸入讀取第一個換行符,並將其刪除。 您必須重複執行此操作才能獲得更多行,並在輸入結束時引發EOFError。 (可能不適合打高爾夫球。)在Python 2中,這是rawinput(prompt)
  • open(0).read() - 在Python 3中, open接受文件描述符 (表示操作系統IO資源的整數),0是stdin的描述符。 它返回一個類似於文件的對象,如sys.stdin - 可能是您打高爾夫球的最佳選擇。
  • open('/dev/stdin').read() - 與open(0)類似,適用於Python 2和3,但不適用於Windows(甚至Cygwin)。
  • fileinput.input() - 在sys.argv[1:]列出的所有文件中返回一個迭代器,如果未給出,則返回stdin。 使用像''.join(fileinput.input())

當然, sysfileinput必須分別導入。

與Python 2和3,Windows,Unix兼容的快速sys.stdin示例

例如,您只需要從sys.stdin read數據,如果您將數據傳遞給stdin:

$ echo foo | python -c "import sys; print(sys.stdin.read())"
foo

文件示例

假設你有一個文件inputs.txt ,我們可以接受該文件並將其寫回:

python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt

較長的答案

這是一個完整的,易於復制的演示,使用兩種方法,內建函數, input (在Python 2中使用raw_input )和sys.stdin 。 數據未修改,因此處理是非操作。

首先,我們來創建一個輸入文件:

$ python -c "print('foo\nbar\nbaz')" > inputs.txt

使用我們已經看到的代碼,我們可以檢查我們是否創建了該文件:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt 
foo
bar
baz

以下是Python 3中sys.stdin.read的幫助:

read(size=-1, /) method of _io.TextIOWrapper instance
    Read at most n characters from stream.

    Read from underlying buffer until we have n characters or we hit EOF.
    If n is negative or omitted, read until EOF.

內建函數, input (Python 2中的raw_input

內置函數input從標準input讀取到新行,該行被剝離(補充print ,默認情況下會添加一個換行符)。直到獲取EOF(文件結束)時才會發生這種情況,此時會引發EOFError

因此,下面是如何使用Python 3中的input (或Python 2中的raw_input )從stdin讀取 - 因此我們創建了一個我們稱為stdindemo.py的Python模塊:

$ python -c "print('try:\n    while True:\n        print(input())\nexcept EOFError:\n    pass')" > stdindemo.py 

讓我們打印出來,以確保它符合我們的預期:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo.py 
try:
    while True:
        print(input())
except EOFError:
    pass

同樣, input讀起來直到換行符並基本上將它從行中刪除。 print添加換行符。 所以當他們都修改輸入時,他們的修改就會被取消。 (所以它們本質上是彼此的補充。)

input獲得文件結束符時,它會引發EOFError,我們忽略它然後退出程序。

而在Linux / Unix上,我們可以通過cat來管道:

$ cat inputs.txt | python -m stdindemo
foo
bar
baz

或者我們可以重定向stdin的文件:

$ python -m stdindemo < inputs.txt 
foo
bar
baz

我們也可以將模塊作為腳本執行:

$ python stdindemo.py < inputs.txt 
foo
bar
baz

以下是Python 3內置input的幫助:

input(prompt=None, /)
    Read a string from standard input.  The trailing newline is stripped.

    The prompt string, if given, is printed to standard output without a
    trailing newline before reading input.

    If the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise EOFError.
    On *nix systems, readline is used if available.

sys.stdin

這裡我們使用sys.stdin製作一個演示腳本。 迭代類文件對象的有效方法是使用類文件對像作為迭代器。 從這個輸入寫入stdout的補充方法是簡單地使用sys.stdout.write

$ python -c "print('import sys\nfor line in sys.stdin:\n    sys.stdout.write(line)')" > stdindemo2.py

將其重新打印出來以確保它看起來正確:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo2.py 
import sys
for line in sys.stdin:
    sys.stdout.write(line)

並將輸入重定向到文件中:

$ python -m stdindemo2 < inputs.txt
foo
bar
baz

打高爾夫球成命令:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz

高爾夫文件描述符

由於stdinstdout文件描述符分別為0和1,我們也可以在Python 3中傳遞這些描述符(不是2,並且請注意,我們仍然需要'w'來寫入stdout)。

如果這可以在你的系統上運行,它將會刮掉更多的字符。

$ python -c "open(1,'w').write(open(0).read())" < inputs.txt
baz
bar
foo

Python 2的io.open也是如此,但是導入需要更多的空間:

$ python -c "from io import open; open(1,'w').write(open(0).read())" < inputs.txt 
foo
bar
baz

解決其他評論和答案

一個評論建議''.join(sys.stdin)但實際上比sys.stdin.read()更長 - 再加上Python必須在內存中創建一個額外的列表(這是str.join在沒有給出列表時的工作方式) - 用於對比:

''.join(sys.stdin)
sys.stdin.read()

最佳答案表明:

import fileinput

for line in fileinput.input():
    pass

但是,由於sys.stdin實現了包括迭代器協議在內的文件API,因此它與此相同:

import sys

for line in sys.stdin:
    pass

另一個答案確實表明這一點 請記住,如果您是在解釋器中執行此操作,則需要在Linux或Mac上執行Ctrl - d ,或在Windows上執行Ctrl - z (在Enter之後),將文件結束字符發送到處理。 此外,該答案建議使用print(line) - 它為最終使用print(line, end='')添加'\n' (如果在Python 2中,則需要from __future__ import print_function )。

fileinput的真實用例是用於讀取一系列文件。


Python還內置了函數input()raw_input() 。 請參閱內置函數下的Python文檔。

例如,

name = raw_input("Enter your name: ")   # Python 2.x

要么

name = input("Enter your name: ")   # Python 3

下面的代碼片段可以幫助你(它會將所有的stdin阻塞到EOF ,讀入一個字符串):

import sys
input_str = sys.stdin.read()
print input_str.split()

以下是學習Python

import sys
data = sys.stdin.readlines()
print "Counted", len(data), "lines."

在Unix上,您可以通過執行以下操作來測試它:

% cat countlines.py | python countlines.py 
Counted 3 lines.

在Windows或DOS上,你可以這樣做:

C:\> type countlines.py | python countlines.py 
Counted 3 lines.

其他人提出的答案是:

for line in sys.stdin:
  print line

是非常簡單和pythonic,但必須注意,腳本將等待直到EOF開始迭代輸入行。

這意味著tail -f error_log | myscript.py tail -f error_log | myscript.py不會按預期處理行。

這種用例的正確腳本是:

while 1:
    try:
        line = sys.stdin.readline()
    except KeyboardInterrupt:
        break

    if not line:
        break

    print line

UPDATE
從註釋中已經清除了,在python 2中,只有可能存在緩衝,所以最終在打印調用發出之前等待緩衝區填滿或EOF。


嘗試這個:

import sys

print sys.stdin.read().upper()

並檢查它:

$ echo "Hello World" | python myFile.py

sys.stdin讀取 ,但要在Windows讀取二進制數據 ,則需要格外小心,因為sys.stdin在文本模式下打開,並且\r\n將其替換為\n

如果檢測到Windows + Python 2,則解決方案是將模式設置為二進制,並且在Python 3上使用sys.stdin.buffer

import sys

PY3K = sys.version_info >= (3, 0)

if PY3K:
    source = sys.stdin.buffer
else:
    # Python 2 on Windows opens sys.stdin in text mode, and
    # binary data that read from it becomes corrupted on \r\n
    if sys.platform == "win32":
        # set sys.stdin to binary mode
        import os, msvcrt
        msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
    source = sys.stdin

b = source.read()

您可以從標準輸入讀取,然後將輸入存儲到“數據”中 ,如下所示:

data = ""
for line in sys.stdin:
    data += line

我遇到的問題是解決方案

import sys

for line in sys.stdin:
    print(line)

如果你沒有將任何數據傳遞給stdin,它將永遠阻塞。 這就是為什麼我喜歡這個答案 :首先檢查stdin上是否有一些數據,然後閱讀它。 這就是我最終做的事情:

import sys
import select

# select(files to read from, files to write to, magic, timeout)
# timeout=0.0 is essential b/c we want to know the asnwer right away
if select.select([sys.stdin], [], [], 0.0)[0]:
    help_file_fragment = sys.stdin.read()
else:
    print("No data passed to stdin", file=sys.stderr)
    sys.exit(2)

我非常驚訝到目前為止還沒有人提到這種黑客行為:

python -c "import sys;print (''.join([l for l in sys.stdin.readlines()]))"

兼容python2和python3


這將回應標準輸入到標準輸出:

import sys
line = sys.stdin.readline()
while line:
    print line,
    line = sys.stdin.readline()

關於這一點:

for line in sys.stdin:

我只是在python 2.7上(根據別人的建議)嘗試了一個非常大的文件,我不推薦它,正是由於上面提到的原因(很長一段時間沒有發生)。

我結束了一個稍微更pythonic的解決方案(它在更大的文件上工作):

with open(sys.argv[1], 'r') as f:
    for line in f:

然後我可以在本地運行腳本:

python myscript.py "0 1 2 3 4..." # can be a multi-line string or filename - any std.in input will work

n = int(raw_input())
for i in xrange(n):
    name, number = raw_input().split()






stdin