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 de {[[0]}. Como faço isso em Python?

 1208
Author: Aaron Hall, 2009-09-20

19 answers

Podes usar o fileinput Módulo:

import fileinput

for line in fileinput.input():
    pass

fileinput irá percorrer todas as linhas na entrada especificada como nomes de ficheiros indicados nos argumentos da linha de comandos, ou a entrada padrão se não forem fornecidos argumentos.

 823
Author: u0b34a0f6ae, 2015-08-31 17:34:21
Há algumas maneiras de o fazer.
  • sys.stdin é um objecto semelhante a um ficheiro no qual pode invocar as funções read ou readlines Se quiser ler tudo ou quiser ler tudo e dividi-lo automaticamente pela newline. (Você precisa import sys para que isto funcione.)

  • Se você quiser pedir ao utilizador para introdução, você pode usar raw_input em Python 2.X, e apenas input 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.

 602
Author: Mark Rushakoff, 2018-06-27 20:21:59
import sys

for line in sys.stdin:
    print line
 342
Author: user303110, 2010-07-20 10:35:53

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
 188
Author: Pat Notz, 2017-09-11 18:47:00
A aprender Python:
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.
 165
Author: Eugene Yokota, 2017-12-10 19:22:29

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.

 87
Author: Massimiliano Torromeo, 2013-12-12 10:33:01
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 chamado sys.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 3 open accepts file descriptors (integers representing operating system IO resources), and 0 is the descriptor of stdin. Ele retorna um objeto parecido com arquivo como sys.stdin - provavelmente a sua melhor aposta para o golfe.
  • open('/dev/stdin').read() - similar a open(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 em sys.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.

Para começar, vamos criar um ficheiro para entradas:
$ 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).

Se isto funcionar no teu sistema, vai cortar mais caracteres.
$ 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.

 56
Author: Aaron Hall, 2018-04-10 21:01:15

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()
 36
Author: rlib, 2012-12-24 06:18:36

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

 29
Author: Emil Lundberg, 2015-08-24 12:53:25

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()
 13
Author: Chandan Kumar, 2018-02-02 20:01:02

Pode ler a partir do stdin e depois armazenar as entradas em "dados" do seguinte modo:

data = ""
for line in sys.stdin:
    data += line
 8
Author: Wei, 2015-02-26 10:52:10

Tenta isto:

import sys

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

E verifique com:

$ echo "Hello World" | python myFile.py
 7
Author: Boubakr, 2013-08-27 15:43:43
Estou espantado por ninguém ter mencionado este hack até agora.
python -c "import sys;print (''.join([l for l in sys.stdin.readlines()]))"

Compatível com python2 e python3

 6
Author: Uri Goren, 2016-11-07 10:15:59

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()
 4
Author: anatoly techtonik, 2016-08-14 05:12:41

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)
 4
Author: SummerBreeze, 2017-11-02 08:49:46
Tive alguns problemas ao fazer com que isto funcionasse para ler sobre tomadas. Quando o 'socket' foi fechado, começou a devolver o texto vazio num ciclo activo. Então esta é a minha solução para ela (que eu só testei no linux, mas espero que funcione em todos os outros sistemas)
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

 2
Author: estani, 2014-10-29 14:57:06

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
 1
Author: szeitlin, 2016-09-17 09:35:29
n = int(raw_input())
for i in xrange(n):
    name, number = raw_input().split()
 0
Author: issam, 2018-03-29 05:37:38

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
    
 0
Author: olibre, 2018-09-27 13:40:34