Como se lê do stdin em Python?
19 answers
sys.stdin
é um objecto semelhante a um ficheiro no qual pode invocar as funçõesread
oureadlines
Se quiser ler tudo ou quiser ler tudo e dividi-lo automaticamente pela newline. (Você precisaimport sys
para que isto funcione.)Se você quiser pedir ao utilizador para introdução, você pode usar
raw_input
em Python 2.X, e apenasinput
em Python 3.Se tu ... se quiser ler as opções da linha de comandos, poderá acedê-las através do sistema .lista argv .
Você provavelmente vai achar Este artigo do Wikibook sobre I / O em Python para ser uma referência útil também.
import sys
for line in sys.stdin:
print line
O Python também tem funções incorporadas input()
e raw_input()
. Veja a documentação em Python em funções incorporadas .
Por exemplo,
name = raw_input("Enter your name: ") # Python 2.x
Ou
name = input("Enter your name: ") # Python 3
import sys
data = sys.stdin.readlines()
print "Counted", len(data), "lines."
No Unix, você pode testá-lo fazendo algo como:
% cat countlines.py | python countlines.py
Counted 3 lines.
Nas janelas ou nos, você faria:
C:\> type countlines.py | python countlines.py
Counted 3 lines.
A resposta proposta por outros:
for line in sys.stdin:
print line
É muito simples e pythonic, mas deve-se notar que o script vai esperar até EOF antes de começar a iterar nas linhas de entrada.
Isto significa que tail -f error_log | myscript.py
não processará as linhas como esperado.
O script correcto para tal caso de uso seria:
while 1:
try:
line = sys.stdin.readline()
except KeyboardInterrupt:
break
if not line:
break
print line
Actualizar
A partir dos comentários foi esclarecido que no python 2 só pode haver buffer envolvido, de modo que você acaba esperando para o buffer para preencher ou EOF antes da chamada de Impressão ser emitida.
Como se lê do stdin em Python? Estou a tentar fazer alguns dos desafios do code golf, mas todos exigem que a entrada seja retirada do stdin. Como faço isso em Python?
Pode usar:
-
sys.stdin
- um objecto de arquivo chamadosys.stdin.read()
para ler tudo. -
input(prompt)
- passe-lhe um prompt opcional para a saída, ele lê de stdin até a primeira linha nova, que ele tira. Terias de fazer isto. repetidamente para obter mais linhas, no final da entrada aumenta EOFError. (Provavelmente não é bom para jogar golfe.) Em Python 2, este érawinput(prompt)
. -
open(0).read()
- in Python 3open
accepts file descriptors (integers representing operating system IO resources), and 0 is the descriptor ofstdin
. Ele retorna um objeto parecido com arquivo comosys.stdin
- provavelmente a sua melhor aposta para o golfe. -
open('/dev/stdin').read()
- similar aopen(0)
, Funciona em Python 2 e 3, mas não em Windows (ou mesmo Cygwin). -
fileinput.input()
- devolve um iterador por linhas em todos os ficheiros listados emsys.argv[1:]
, ou stdin, se não for indicado. Usar como''.join(fileinput.input())
.
Ambos sys
e fileinput
devem ser importados, respectivamente, é claro.
Exemplos rápidos sys.stdin
compatíveis com Python 2 e 3, Windows, Unix
Só precisa de read
de sys.stdin
, por exemplo, se encaminhar dados para stdin:
$ echo foo | python -c "import sys; print(sys.stdin.read())"
foo
Exemplo de ficheiro
Digamos que tens um ficheiro, podemos aceitar isso. arquive e escreva de volta:python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
Resposta mais longa
Aqui está uma demonstração completa e facilmente replicável, usando dois métodos, a função builtin, input
(use raw_input
em Python 2), e sys.stdin
. Os dados não são modificados, então o processamento é uma não Operação.
$ python -c "print('foo\nbar\nbaz')" > inputs.txt
E usando o código que já vimos, podemos verificar se criamos o arquivo:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz
Aqui está a ajuda do 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.
Função de construção, input
(raw_input
em Python 2)
A função builtin input
lê-se de uma entrada padrão até uma nova linha, que é despojada (complementando print
, que adiciona uma nova linha por omissão.) Isto ocorre até que ele obtém EOF (fim do arquivo), em que ponto ele levanta EOFError
.
Assim, aqui está como você pode usar input
em Python 3 (ou raw_input
em Python 2) para ler a partir do stdin - então nós criamos um módulo Python que chamamos stdindemo.py:
$ python -c "print('try:\n while True:\n print(input())\nexcept EOFError:\n pass')" > stdindemo.py
E vamos imprime - o para garantir que é como esperamos.
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo.py
try:
while True:
print(input())
except EOFError:
pass
Novamente, input
lê até a linha nova e essencialmente tira-a da linha. print
adiciona uma nova linha. Então, enquanto ambos modificam a entrada, suas modificações cancelam. (Então eles são essencialmente o complemento um do outro.)
E quando input
obtém o carácter de fim de ficheiro, aumenta o EOFError, que ignoramos e depois saímos do programa.
E no Linux / Unix, podemos fazer pipe a partir do cat:
$ cat inputs.txt | python -m stdindemo
foo
bar
baz
Ou nós pode redireccionar o ficheiro do stdin:
$ python -m stdindemo < inputs.txt
foo
bar
baz
Também podemos executar o módulo como um script:
$ python stdindemo.py < inputs.txt
foo
bar
baz
Aqui está a ajuda na construção do 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
Aqui fazemos um programa de demonstração usando sys.stdin
. A maneira eficiente de iterar sobre um objeto semelhante a um arquivo é usar o objeto semelhante a um arquivo como um iterador. O método complementar para escrever ao stdout a partir desta entrada é simplesmente usar sys.stdout.write
:
$ python -c "print('import sys\nfor line in sys.stdin:\n sys.stdout.write(line)')" > stdindemo2.py
Imprime-o para ter a certeza. parece certo.
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo2.py
import sys
for line in sys.stdin:
sys.stdout.write(line)
E redireccionar as entradas para o ficheiro:
$ python -m stdindemo2 < inputs.txt
foo
bar
baz
Joguei num comando:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz
Descritores de ficheiros para o golfe
Uma vez que os descritores de ficheiros para stdin
e stdout
são 0 e 1 respectivamente, também podemos passar esses para open
em Python 3 (NÃO 2, e note que ainda precisamos do 'w' para escrever para stdout).
$ python -c "open(1,'w').write(open(0).read())" < inputs.txt
baz
bar
foo
Python 2's io.open
Faz isto também, mas a importação requer muito mais espaço:
$ python -c "from io import open; open(1,'w').write(open(0).read())" < inputs.txt
foo
bar
baz
Endereçando outros comentários e Respostas
Um comentário sugere ''.join(sys.stdin)
mas isso é mais longo do que sys.stdin.read () - plus Python must create an extra list in memory (that's how str.join
works when not given a list) - for contrast:
''.join(sys.stdin)
sys.stdin.read()
A resposta de cima sugere:
import fileinput
for line in fileinput.input():
pass
Mas, como sys.stdin
implementa a API de ficheiros, incluindo o protocolo iterator, isso é exactamente o mesmo que isto:
import sys
for line in sys.stdin:
pass
Outra resposta sugere isto. Lembre-se que se o fizer num intérprete, terá de fazer Ctrl-d se estiver no Linux ou no Mac, ou Ctrl-z no Windows (após digite ) para enviar o carácter de fim de ficheiro para o processo. Além disso, essa resposta sugere print(line)
- o que adiciona um '\n'
ao uso final print(line, end='')
em vez disso (se no Python 2, você vai precisar de from __future__ import print_function
).
O caso de Utilização real para fileinput
é para ler em uma série de arquivos.
Isto fará eco da entrada normal para a saída normal:
import sys
line = sys.stdin.readline()
while line:
print line,
line = sys.stdin.readline()
Baseado em todos os anwers que usam sys.stdin
, Você também pode fazer algo como o seguinte para ler a partir de um ficheiro de argumentos se pelo menos um argumento existir, e voltar para o stdin caso contrário:
import sys
f = open(sys.argv[1]) if len(sys.argv) > 1 else sys.stdin
for line in f:
# Do your stuff
E usa-o como
$ python do-my-stuff.py infile.txt
Ou
$ cat infile.txt | python do-my-stuff.py
Ou mesmo
$ python do-my-stuff.py < infile.txt
Isso faria com que o seu script Python se comportasse como muitos programas GNU / Unix como cat
, grep
e sed
O seguinte chip de código irá ajudá-lo (ele irá ler todo o bloqueio de stdin até EOF
, em uma cadeia):
import sys
input_str = sys.stdin.read()
print input_str.split()
Pode ler a partir do stdin e depois armazenar as entradas em "dados" do seguinte modo:
data = ""
for line in sys.stdin:
data += line
Tenta isto:
import sys
print sys.stdin.read().upper()
E verifique com:
$ echo "Hello World" | python myFile.py
python -c "import sys;print (''.join([l for l in sys.stdin.readlines()]))"
Compatível com python2 e python3
Leia de sys.stdin
, mas para Leia dados binários no Windows , você precisa de ter cuidado extra, porque {[1] } Existe Aberto no modo de texto e ele irá corromper \r\n
substituindo-os por \n
.
A solução é definir o modo binário se o Windows + Python 2 for detectado,e no Python 3 Usar 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()
O problema que tenho com a solução
import sys
for line in sys.stdin:
print(line)
É que se não passar dados ao stdin, vai bloquear para sempre. É por isso que eu amo esta Resposta : Verifique se há alguns dados sobre o stdin primeiro, e depois leia-o. Foi isto que acabei por fazer:
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)
import sys, os
sep=os.linesep
while sep == os.linesep:
data = sys.stdin.readline()
sep = data[-len(os.linesep):]
print '> "%s"' % data.strip()
Por isso, se começar a ouvir num 'socket', irá funcionar correctamente (por exemplo, na bash):
while :; do nc -l 12345 | python test.py ; done
E você pode chamá-lo com telnet ou apenas apontar um navegador para localhost:12345
Em relação a isto:
for line in sys.stdin:
Eu apenas tentei em python 2.7 (seguindo a sugestão de outra pessoa) para um arquivo muito grande, e eu não recomendo, precisamente pelas razões mencionadas acima (nada acontece por um longo tempo).
Acabei com uma solução um pouco mais pythonic (e funciona em ficheiros maiores):
with open(sys.argv[1], 'r') as f:
for line in f:
Então eu posso executar o script localmente como:
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()
Como complemento destas respostas, também pode utilizar argparse
isso também é compatível com python2. 7 . Exemplo compatível tanto python2 quanto python3:
#!/usr/bin/python
import argparse
import sys
parser = argparse.ArgumentParser()
parser.add_argument('in', default=sys.stdin, type=argparse.FileType('r'), nargs='?')
args = parser.parse_args()
data = args.in.read()
Você pode executar este script de duas maneiras:
-
Utilizar
stdin
:echo 'foo bar' | ./above-script.py
-
Usando um argumento de nome de ficheiro:
echo 'foo bar' > text-file ./above-script.py text-file