Câu trả lời:
Bạn có thể sử dụng fileinput
mô-đun:
import fileinput
for line in fileinput.input():
pass
fileinput
sẽ lặp qua tất cả các dòng trong đầu vào được chỉ định dưới dạng tên tệp được đưa ra trong các đối số dòng lệnh hoặc đầu vào tiêu chuẩn nếu không có đối số nào được cung cấp.
Lưu ý: line
sẽ chứa một dòng mới; để loại bỏ nó sử dụngline.rstrip()
Có một vài cách để làm điều đó.
sys.stdin
là một đối tượng giống như tệp mà bạn có thể gọi các hàm read
hoặc readlines
nếu bạn muốn đọc mọi thứ hoặc bạn muốn đọc mọi thứ và tự động phân tách nó theo dòng mới. (Bạn cần import sys
để làm việc này.)
Nếu bạn muốn nhắc người dùng nhập liệu, bạn có thể sử dụng raw_input
trong Python 2.X và chỉ input
trong Python 3.
Nếu bạn thực sự chỉ muốn đọc các tùy chọn dòng lệnh, bạn có thể truy cập chúng thông qua danh sách sys.argv .
Bạn có thể sẽ thấy bài viết Wikibook này về I / O trong Python là một tài liệu tham khảo hữu ích.
import sys
for line in sys.stdin:
print(line)
Lưu ý rằng điều này sẽ bao gồm một ký tự dòng mới ở cuối. Để xóa dòng mới ở cuối, hãy sử dụng line.rstrip()
như @brittohalloran nói.
\r\n
kết thúc dòng
Python cũng có các hàm dựng sẵn input()
và raw_input()
. Xem tài liệu Python dưới Hàm dựng sẵn .
Ví dụ,
name = raw_input("Enter your name: ") # Python 2.x
hoặc là
name = input("Enter your name: ") # Python 3
Đây là từ Học Python :
import sys
data = sys.stdin.readlines()
print "Counted", len(data), "lines."
Trên Unix, bạn có thể kiểm tra nó bằng cách thực hiện một số thứ như:
% cat countlines.py | python countlines.py
Counted 3 lines.
Trên Windows hoặc DOS, bạn sẽ làm:
C:\> type countlines.py | python countlines.py
Counted 3 lines.
print(sum(chunk.count('\n') for chunk in iter(partial(sys.stdin.read, 1 << 15), '')))
. xemwc-l.py
cat
ở đây là dư thừa. Yêu cầu chính xác cho các hệ thống Unix là python countlines.py < countlines.py
.
readlines()
. Các đối tượng tệp được dự định lặp đi lặp lại mà không cụ thể hóa tất cả dữ liệu trong bộ nhớ.
Làm thế nào để bạn đọc từ stdin trong Python?
Tôi đang cố gắng thực hiện một số thử thách golf mã, nhưng tất cả chúng đều yêu cầu đầu vào phải được lấy từ stdin. Làm thế nào để tôi có được điều đó trong Python?
Bạn có thể dùng:
sys.stdin
- Một đối tượng giống như tệp - gọi sys.stdin.read()
để đọc mọi thứ.input(prompt)
- chuyển cho nó một dấu nhắc tùy chọn để xuất ra, nó đọc từ stdin cho đến dòng mới đầu tiên, nó thoát ra. Bạn sẽ phải làm điều này nhiều lần để có được nhiều dòng hơn, vào cuối đầu vào, nó sẽ tăng EOFError. (Có lẽ không tuyệt vời cho việc chơi gôn.) Trong Python 2, đây là rawinput(prompt)
.open(0).read()
- Trong Python 3, hàm dựng sẵn open
chấp nhận bộ mô tả tệp (số nguyên biểu thị tài nguyên IO của hệ điều hành) và 0 là bộ mô tả của stdin
. Nó trả về một đối tượng giống như tệp sys.stdin
- có lẽ là đặt cược tốt nhất của bạn để chơi gôn. Trong Python 2, đây là io.open
.open('/dev/stdin').read()
- tương tự open(0)
, hoạt động trên Python 2 và 3, nhưng không hoạt động trên Windows (hoặc thậm chí Cygwin).fileinput.input()
- trả về một trình vòng lặp qua các dòng trong tất cả các tệp được liệt kê trong sys.argv[1:]
hoặc stdin nếu không được cung cấp. Sử dụng như thế nào ''.join(fileinput.input())
.Tất cả sys
và fileinput
phải được nhập khẩu, tương ứng, tất nhiên.
sys.stdin
ví dụ nhanh tương thích với Python 2 và 3, Windows, UnixBạn chỉ cần read
từ sys.stdin
, ví dụ, nếu bạn chuyển dữ liệu sang stdin:
$ echo foo | python -c "import sys; print(sys.stdin.read())"
foo
Chúng ta có thể thấy đó sys.stdin
là trong chế độ văn bản mặc định:
>>> import sys
>>> sys.stdin
<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>
Giả sử bạn có một tệp, inputs.txt
chúng tôi có thể chấp nhận tệp đó và viết lại:
python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
Đây là một bản demo hoàn chỉnh, có thể sao chép dễ dàng, sử dụng hai phương thức, hàm dựng sẵn, input
(sử dụng raw_input
trong Python 2) và sys.stdin
. Dữ liệu không được sửa đổi, vì vậy việc xử lý là không hoạt động.
Để bắt đầu, hãy tạo một tệp cho đầu vào:
$ python -c "print('foo\nbar\nbaz')" > inputs.txt
Và bằng cách sử dụng mã chúng ta đã thấy, chúng ta có thể kiểm tra xem chúng ta đã tạo tệp chưa:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz
Đây là sự trợ giúp sys.stdin.read
từ Python 3:
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
( raw_input
trong Python 2)Hàm dựng sẵn input
đọc từ đầu vào tiêu chuẩn cho đến một dòng mới, được loại bỏ (bổ sung print
, thêm một dòng mới theo mặc định.) Điều này xảy ra cho đến khi nó nhận được EOF (End Of File), tại đó nó tăng lên EOFError
.
Vì vậy, đây là cách bạn có thể sử dụng input
trong Python 3 (hoặc raw_input
trong Python 2) để đọc từ stdin - vì vậy chúng tôi tạo một mô-đun Python mà chúng tôi gọi là stdindemo.py:
$ python -c "print('try:\n while True:\n print(input())\nexcept EOFError:\n pass')" > stdindemo.py
Và hãy in nó ra để đảm bảo nó như chúng ta mong đợi:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo.py
try:
while True:
print(input())
except EOFError:
pass
Một lần nữa, input
đọc lên cho đến dòng mới và về cơ bản tước nó khỏi dòng. print
thêm một dòng mới. Vì vậy, trong khi cả hai đều sửa đổi đầu vào, sửa đổi của họ hủy bỏ. (Vì vậy, về cơ bản chúng là bổ sung cho nhau.)
Và khi input
nhận được ký tự cuối tệp, nó sẽ tăng EOFError, cái mà chúng ta bỏ qua và sau đó thoát khỏi chương trình.
Và trên Linux / Unix, chúng ta có thể chuyển từ mèo:
$ cat inputs.txt | python -m stdindemo
foo
bar
baz
Hoặc chúng ta chỉ có thể chuyển hướng tệp từ stdin:
$ python -m stdindemo < inputs.txt
foo
bar
baz
Chúng tôi cũng có thể thực thi mô-đun như một kịch bản:
$ python stdindemo.py < inputs.txt
foo
bar
baz
Đây là trợ giúp về nội dung input
từ Python 3:
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
Ở đây chúng tôi tạo một kịch bản demo bằng cách sử dụng sys.stdin
. Cách hiệu quả để lặp lại một đối tượng giống như tệp là sử dụng đối tượng giống như tệp làm trình vòng lặp. Phương pháp bổ sung để ghi vào thiết bị xuất chuẩn từ đầu vào này chỉ đơn giản là sử dụng sys.stdout.write
:
$ python -c "print('import sys\nfor line in sys.stdin:\n sys.stdout.write(line)')" > stdindemo2.py
In nó ra để đảm bảo nó trông đúng:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo2.py
import sys
for line in sys.stdin:
sys.stdout.write(line)
Và chuyển hướng đầu vào vào tập tin:
$ python -m stdindemo2 < inputs.txt
foo
bar
baz
Chơi gôn thành một lệnh:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz
Vì các mô tả tệp cho stdin
và stdout
lần lượt là 0 và 1, chúng ta cũng có thể chuyển chúng cho open
Python 3 (không phải 2 và lưu ý rằng chúng ta vẫn cần 'w' để ghi vào thiết bị xuất chuẩn).
Nếu điều này hoạt động trên hệ thống của bạn, nó sẽ loại bỏ nhiều ký tự hơn.
$ python -c "open(1,'w').write(open(0).read())" < inputs.txt
baz
bar
foo
Python 2 cũng io.open
làm điều này, nhưng quá trình nhập chiếm nhiều không gian hơn:
$ python -c "from io import open; open(1,'w').write(open(0).read())" < inputs.txt
foo
bar
baz
Một nhận xét gợi ý ''.join(sys.stdin)
cho việc chơi golf nhưng thực sự dài hơn sys.stdin.read () - cộng với Python phải tạo thêm một danh sách trong bộ nhớ (đó là cách str.join
hoạt động khi không được đưa ra danh sách) - ngược lại:
''.join(sys.stdin)
sys.stdin.read()
Câu trả lời hàng đầu cho thấy:
import fileinput
for line in fileinput.input():
pass
Nhưng, vì sys.stdin
triển khai API tệp, bao gồm cả giao thức iterator, điều đó cũng giống như sau:
import sys
for line in sys.stdin:
pass
Câu trả lời khác không đề nghị này. Chỉ cần nhớ rằng nếu bạn làm điều đó trong một trình thông dịch, bạn sẽ cần phải làm Ctrl- dnếu bạn đang dùng Linux hoặc Mac hoặc Ctrl- ztrên Windows (sau Enter) để gửi ký tự cuối tệp đến quy trình. Ngoài ra, câu trả lời đó cho thấy print(line)
- bổ sung thêm '\n'
vào cuối - sử dụng print(line, end='')
thay thế (nếu trong Python 2, bạn sẽ cần from __future__ import print_function
).
Trường hợp sử dụng thực tế fileinput
là để đọc trong một loạt các tệp.
Câu trả lời được đề xuất bởi người khác:
for line in sys.stdin:
print line
là rất đơn giản và pythonic, nhưng phải lưu ý rằng tập lệnh sẽ đợi cho đến khi EOF trước khi bắt đầu lặp lại trên các dòng đầu vào.
Điều này có nghĩa là tail -f error_log | myscript.py
sẽ không xử lý các dòng như mong đợi.
Kịch bản chính xác cho trường hợp sử dụng như vậy sẽ là:
while 1:
try:
line = sys.stdin.readline()
except KeyboardInterrupt:
break
if not line:
break
print line
CẬP NHẬT
Từ các bình luận đã bị xóa rằng trên python 2 chỉ có thể có bộ đệm liên quan, do đó cuối cùng bạn chờ đợi bộ đệm điền hoặc EOF trước khi lệnh in được phát ra.
for line in sys.stdin:
mẫu không chờ EOF. Nhưng nếu bạn kiểm tra trên các tệp rất nhỏ, các phản hồi có thể bị đệm. Kiểm tra với nhiều dữ liệu hơn để thấy rằng nó đọc kết quả trung gian.
print line
không đánh thức trong 3.1.3, nhưng print(line)
không.
for line in sys.stdin:
không "chặn cho đến EOF". Có một lỗi đọc trước trong Python 2 làm trì hoãn các dòng cho đến khi bộ đệm tương ứng đầy. Đây là một vấn đề đệm không liên quan đến EOF. Để giải quyết, sử dụng for line in iter(sys.stdin.readline, ''):
(sử dụng io.open()
cho các tệp thông thường). Bạn không cần nó trong Python 3.
Dựa trên tất cả các anwers đang sử dụng sys.stdin
, bạn cũng có thể thực hiện một số thao tác như sau để đọc từ tệp đối số nếu có ít nhất một đối số tồn tại và quay lại stdin nếu không:
import sys
f = open(sys.argv[1]) if len(sys.argv) > 1 else sys.stdin
for line in f:
# Do your stuff
và sử dụng nó như là một trong hai
$ python do-my-stuff.py infile.txt
hoặc là
$ cat infile.txt | python do-my-stuff.py
hoặc thậm chí
$ python do-my-stuff.py < infile.txt
Điều đó sẽ làm cho tập lệnh Python của bạn hoạt động giống như nhiều chương trình GNU / Unix như cat
, grep
và sed
.
argparse
là một giải pháp dễ dàngVí dụ tương thích với cả hai phiên bản Python 2 và 3:
#!/usr/bin/python
import argparse
import sys
parser = argparse.ArgumentParser()
parser.add_argument('infile',
default=sys.stdin,
type=argparse.FileType('r'),
nargs='?')
args = parser.parse_args()
data = args.infile.read()
Bạn có thể chạy tập lệnh này theo nhiều cách:
1. Sử dụng stdin
echo 'foo bar' | ./above-script.py
hoặc ngắn hơn bằng cách thay thế echo
bằng chuỗi ở đây :
./above-script.py <<< 'foo bar'
2. Sử dụng đối số tên tệp
echo 'foo bar' > my-file.data
./above-script.py my-file.data
3. Sử dụng stdin
thông qua tên tệp đặc biệt-
echo 'foo bar' | ./above-script.py -
add_argument('--in'
và sau đó chuyển sang tập lệnh và thêm --in -
vào dòng lệnh. PS in
không phải là một tên rất tốt cho một biến / thuộc tính.
in
không chỉ là một tên xấu cho một biến, nó là bất hợp pháp. args.in.read()
sẽ đưa ra lỗi UnlimitedSyntax vì in
từ khóa dành riêng. Chỉ đơn giản là có thể đổi tên cho infile
giống như python argparse tài liệu làm: docs.python.org/3/library/...
Đoạn mã sau đây sẽ giúp bạn (nó sẽ đọc tất cả các stdin chặn cho đến EOF
một chuỗi):
import sys
input_str = sys.stdin.read()
print input_str.split()
Tôi khá ngạc nhiên khi không có ai đề cập đến vụ hack này cho đến nay:
python -c "import sys; set(map(sys.stdout.write,sys.stdin))"
trong python2 bạn có thể bỏ set()
cuộc gọi, nhưng nó sẽ chuyển từ
readlines
phân chia thành dòng và sau đó join
một lần nữa? Bạn chỉ có thể viếtprint(sys.stdin.read())
write
lợi nhuận None
và kích thước đã đặt sẽ không bao giờ lớn hơn 1 ( =len(set([None]))
)
Bạn có thể đọc từ stdin và sau đó lưu trữ dữ liệu vào "dữ liệu" như sau:
data = ""
for line in sys.stdin:
data += line
data = sys.stdin.read()
, mà không có vấn đề nối chuỗi lặp lại.
Đọc từ sys.stdin
, nhưng để đọc dữ liệu nhị phân trên Windows , bạn cần hết sức cẩn thận, vì sys.stdin
đã mở ở chế độ văn bản và nó sẽ bị hỏng \r\n
thay thế chúng bằng \n
.
Giải pháp là đặt chế độ thành nhị phân nếu phát hiện Windows + Python 2 và trên Python 3 sử dụng 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()
Tôi sử dụng phương thức sau, nó trả về một chuỗi từ stdin (Tôi sử dụng nó để phân tích cú pháp json). Nó hoạt động với pipe và prompt trên Windows (chưa được thử nghiệm trên Linux). Khi nhắc, hai ngắt dòng cho biết kết thúc đầu vào.
def get_from_stdin():
lb = 0
stdin = ''
for line in sys.stdin:
if line == "\n":
lb += 1
if lb == 2:
break
else:
lb = 0
stdin += line
return stdin
Vấn đề tôi có với giải pháp
import sys
for line in sys.stdin:
print(line)
là nếu bạn không chuyển bất kỳ dữ liệu nào cho stdin, nó sẽ bị chặn vĩnh viễn. Đó là lý do tại sao tôi thích câu trả lời này : kiểm tra xem có dữ liệu nào về stdin trước không, sau đó đọc nó. Đây là những gì tôi đã làm:
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)
select
được gọi; hoặc bạn cũng có thể gặp vấn đề nếu stdin được kết nối với một tệp trên phương tiện chậm (mạng, CD, băng, v.v.). Bạn nói rằng "nếu bạn không chuyển bất kỳ dữ liệu nào cho stdin, nó sẽ bị chặn vĩnh viễn." là một vấn đề , nhưng tôi sẽ nói đó là một tính năng . Hầu hết các chương trình CLI (ví dụ cat
) hoạt động theo cách này và chúng được mong đợi. EOF là điều duy nhất bạn nên phụ thuộc vào để phát hiện kết thúc của đầu vào.
Tôi đã có một số vấn đề khi làm cho nó hoạt động để đọc qua các ổ cắm được dẫn đến nó. Khi ổ cắm đã đóng, nó bắt đầu trả về chuỗi rỗng trong một vòng lặp hoạt động. Vì vậy, đây là giải pháp của tôi cho nó (mà tôi chỉ thử nghiệm trong linux, nhưng hy vọng nó hoạt động trong tất cả các hệ thống khác)
import sys, os
sep=os.linesep
while sep == os.linesep:
data = sys.stdin.readline()
sep = data[-len(os.linesep):]
print '> "%s"' % data.strip()
Vì vậy, nếu bạn bắt đầu nghe trên một ổ cắm, nó sẽ hoạt động bình thường (ví dụ như trong bash):
while :; do nc -l 12345 | python test.py ; done
Và bạn có thể gọi nó bằng telnet hoặc chỉ một trình duyệt tới localhost: 12345
Về vấn đề này:
for line in sys.stdin:
Tôi vừa thử nó trên python 2.7 (theo gợi ý của người khác) cho một tệp rất lớn và tôi không khuyên dùng nó, chính xác là vì những lý do được đề cập ở trên (không có gì xảy ra trong một thời gian dài).
Tôi đã kết thúc với một giải pháp pythonic hơn một chút (và nó hoạt động trên các tệp lớn hơn):
with open(sys.argv[1], 'r') as f:
for line in f:
Sau đó, tôi có thể chạy tập lệnh cục bộ như:
python myscript.py "0 1 2 3 4..." # can be a multi-line string or filename - any std.in input will work
sys.stdin
dưới dạng đối số dòng lệnh cho tập lệnh.
sys.stdin
như là một đối số dòng lệnh cho kịch bản? Đối số là chuỗi và luồng là các đối tượng giống như tệp, chúng không giống nhau.
sys.stdin
là một đối tượng giống như tệp
Đối với Python 3 , đó sẽ là:
# Filename e.g. cat.py
import sys
for line in sys.stdin:
print(line, end="")
Về cơ bản, đây là một dạng mèo đơn giản (1), vì nó không thêm dòng mới sau mỗi dòng. Bạn có thể sử dụng điều này (sau khi Bạn đã đánh dấu tệp thực thi bằng cách sử dụng, chmod +x cat.py
chẳng hạn như:
echo Hello | ./cat.py
Khi sử dụng -c
lệnh, như một cách khó khăn, thay vì đọc stdin
(và linh hoạt hơn trong một số trường hợp), bạn có thể truyền lệnh shell shell cho lệnh python của mình bằng cách đặt lệnh sell trong dấu ngoặc đơn trong dấu ngoặc đơn bắt đầu bằng $
dấu.
ví dụ
python3 -c "import sys; print(len(sys.argv[1].split('\n')))" "$(cat ~/.goldendict/history)"
Điều này sẽ đếm số lượng dòng từ tệp lịch sử của goldendict.