Estou tentando fazer alguns dos desafios do código de golfe , mas todos exigem que a entrada seja retirada stdin
. Como faço para obtê-lo no Python?
1473
Estou tentando fazer alguns dos desafios do código de golfe , mas todos exigem que a entrada seja retirada stdin
. Como faço para obtê-lo no Python?
Você pode usar o fileinput
módulo:
import fileinput
for line in fileinput.input():
pass
fileinput
percorrerá todas as linhas da entrada especificada como nomes de arquivo fornecidos nos argumentos da linha de comandos ou a entrada padrão se nenhum argumento for fornecido.
Nota: line
conterá uma nova linha à direita; para removê-lo useline.rstrip()
Existem algumas maneiras de fazer isso.
sys.stdin
é um objeto parecido com um arquivo no qual você pode chamar funçõesread
oureadlines
se deseja ler tudo ou se deseja ler tudo e dividi-lo por nova linha automaticamente. (Você precisa queimport sys
isso funcione.)Se você deseja solicitar uma entrada ao usuário, pode usá-lo
raw_input
no Python 2.X e apenasinput
no Python 3.Se você realmente quiser apenas ler as opções da linha de comando, poderá acessá-las através da lista sys.argv .
Você provavelmente encontrará este artigo do Wikibook sobre E / S em Python como uma referência útil também.
fonte
Observe que isso incluirá um caractere de nova linha no final. Para remover a nova linha no final, use
line.rstrip()
como @brittohalloran disse.fonte
\r\n
finais de linhaO Python também possui funções internas
input()
eraw_input()
. Veja a documentação do Python em Funções internas .Por exemplo,
ou
fonte
Aqui está do Learning Python :
No Unix, você pode testá-lo fazendo algo como:
No Windows ou DOS, você faria:
fonte
print(sum(chunk.count('\n') for chunk in iter(partial(sys.stdin.read, 1 << 15), '')))
. Vejawc-l.py
cat
aqui é redundante. A chamada correta para sistemas Unix épython countlines.py < countlines.py
.readlines()
. Objetos de arquivo devem ser iterados sem materializar todos os dados na memória.Você pode usar:
sys.stdin
- Um objeto parecido com um arquivo - liguesys.stdin.read()
para ler tudo.input(prompt)
- passe um prompt opcional para a saída, ele lê do stdin até a primeira nova linha, que é removida. Você teria que fazer isso repetidamente para obter mais linhas; no final da entrada, gera EOFError. (Provavelmente não é bom para jogar golfe.) No Python 2, é issorawinput(prompt)
.open(0).read()
- No Python 3, a função internaopen
aceita descritores de arquivo (números inteiros que representam recursos de E / S do sistema operacional) e 0 é o descritor destdin
. Ele retorna um objeto parecido com um arquivo comosys.stdin
- provavelmente sua melhor aposta no golfe. No Python 2, é issoio.open
.open('/dev/stdin').read()
- semelhante aopen(0)
, funciona em Python 2 e 3, mas não no Windows (ou mesmo no Cygwin).fileinput.input()
- retorna um iterador sobre as linhas em todos os arquivos listados emsys.argv[1:]
, ou stdin, se não for fornecido. Use como''.join(fileinput.input())
.Ambos
sys
efileinput
devem ser importados, respectivamente, é claro.sys.stdin
Exemplos rápidos compatíveis com Python 2 e 3, Windows, UnixVocê só precisa
read
desys.stdin
, por exemplo, se os dados de tubulação para stdin:Podemos ver que
sys.stdin
está no modo de texto padrão:exemplo de arquivo
Digamos que você tenha um arquivo,
inputs.txt
podemos aceitá-lo e escrevê-lo novamente:Resposta mais longa
Aqui está uma demonstração completa e facilmente replicável, usando dois métodos, a função embutida
input
(usoraw_input
no Python 2) esys.stdin
. Os dados não são modificados, portanto, o processamento é uma não operação.Para começar, vamos criar um arquivo para entradas:
E usando o código que já vimos, podemos verificar se criamos o arquivo:
Aqui está a ajuda
sys.stdin.read
do Python 3:Função interna
input
(raw_input
em Python 2)A função incorporada
input
lê da entrada padrão até uma nova linha, que é removida (complementandoprint
, que adiciona uma nova linha por padrão.) Isso ocorre até que receba EOF (Fim do arquivo), momento em que aumentaEOFError
.Assim, aqui está como você pode usar
input
no Python 3 (ouraw_input
no Python 2) para ler a partir de stdin - então criamos um módulo Python que chamamos stdindemo.py:E vamos imprimi-lo novamente para garantir que seja como esperamos:
Novamente,
input
lê até a nova linha e retira-a essencialmente da linha.print
adiciona uma nova linha. Portanto, enquanto ambos modificam a entrada, suas modificações são canceladas. (Portanto, eles são essencialmente o complemento um do outro.)E quando
input
obtém o caractere de fim de arquivo, gera EOFError, que ignoramos e saímos do programa.E no Linux / Unix, podemos canalizar do gato:
Ou podemos apenas redirecionar o arquivo do stdin:
Também podemos executar o módulo como um script:
Aqui está a ajuda sobre o built-in
input
do Python 3:sys.stdin
Aqui nós fazemos um script de demonstração usando
sys.stdin
. A maneira eficiente de iterar sobre um objeto semelhante a arquivo é usar o objeto semelhante a arquivo como um iterador. O método complementar para escrever no stdout a partir desta entrada é simplesmente usarsys.stdout.write
:Imprima-o novamente para garantir a aparência correta:
E redirecionando as entradas para o arquivo:
Golfed em um comando:
Descritores de arquivo para golfe
Como os descritores de arquivo para
stdin
estdout
são 0 e 1, respectivamente, também podemos transmiti-los para oopen
Python 3 (não 2, e observe que ainda precisamos do 'w' para escrever no stdout).Se isso funcionar no seu sistema, ele eliminará mais caracteres.
O Python 2 também
io.open
faz isso, mas a importação ocupa muito mais espaço:Abordando outros comentários e respostas
Um comentário sugere
''.join(sys.stdin)
para jogar golfe, mas na verdade é mais longo que sys.stdin.read () - além disso, o Python deve criar uma lista extra na memória (é assim questr.join
funciona quando não é fornecida uma lista) - para contraste:A resposta principal sugere:
Mas, como
sys.stdin
implementa a API do arquivo, incluindo o protocolo do iterador, é o mesmo:Outra resposta que sugerem isso. Lembre-se de que, se você fizer isso em um intérprete, precisará fazer isso Ctrl- dse estiver no Linux ou Mac ou Ctrl- zno Windows (depois Enter) para enviar o caractere de fim de arquivo ao processo. Além disso, essa resposta sugere
print(line)
- que adiciona um'\n'
ao final - useprint(line, end='')
(em Python 2, você precisaráfrom __future__ import print_function
).O caso de uso real para
fileinput
é para ler em uma série de arquivos.fonte
A resposta proposta por outros:
é muito simples e pitônico, mas deve-se notar que o script aguardará até o EOF antes de começar a iterar nas linhas de entrada.
Isso significa que
tail -f error_log | myscript.py
não processará as linhas conforme o esperado.O script correto para esse caso de uso seria:
ATUALIZAÇÃO
A partir dos comentários, foi esclarecido que somente no python 2 pode haver buffer envolvido, para que você espere que o buffer seja preenchido ou EOF antes da emissão da chamada de impressão.
fonte
for line in sys.stdin:
padrão não espera pelo EOF. Mas se você testar em arquivos muito pequenos, as respostas poderão ficar em buffer. Teste com mais dados para ver se ele lê resultados intermediários.print line
não acordou no 3.1.3, masprint(line)
sim.for line in sys.stdin:
não "bloqueia até EOF". Há um bug de leitura antecipada no Python 2 que atrasa as linhas até que o buffer correspondente esteja cheio. É um problema de buffer não relacionado ao EOF. Para solução alternativa, usefor line in iter(sys.stdin.readline, ''):
(useio.open()
para arquivos comuns). Você não precisa dele em Python 3.Isso fará eco da entrada padrão para a saída padrão:
fonte
Com base em todas as respostas que
sys.stdin
você usa , você também pode fazer algo como o seguinte para ler um arquivo de argumento, se pelo menos um argumento existir, e voltar ao stdin caso contrário:e use-o como
ou
ou mesmo
Isso faria seu script Python se comportar como muitos programas GNU / Unix, como
cat
,grep
esed
.fonte
argparse
é uma solução fácilExemplo compatível com as versões 2 e 3 do Python:
Você pode executar este script de várias maneiras:
1. Usando
stdin
ou mais curto, substituindo
echo
por aqui string :2. Usando um argumento de nome de arquivo
3. Usando
stdin
através do nome de arquivo especial-
fonte
add_argument('--in'
e, em seguida, canalizar para o script e adicionar--in -
à linha de comando. PSin
não é um nome muito bom para uma variável / atributo.in
não é apenas um nome ruim para uma variável, é ilegal.args.in.read()
irá gerar o erro InvalidSyntax devido àin
palavra-chave reservada. Pode simplesmente mudar o nome parainfile
gostar do que os documentos do python argparse fazem: docs.python.org/3/library/…O seguinte chip de código o ajudará (ele lerá todos os stdin bloqueando até
EOF
em uma sequência):fonte
Estou bastante surpreso que ninguém tenha mencionado esse hack até agora:
em python2, você pode interromper a
set()
chamada, mas pode dizer o que quer que sejafonte
readlines
que usar essa divisão em linhas e depoisjoin
novamente? Você pode simplesmente escreverprint(sys.stdin.read())
write
retornaNone
, e o tamanho do conjunto nunca seria maior que 1 (=len(set([None]))
)Tente o seguinte:
e verifique com:
fonte
Você pode ler do stdin e, em seguida, armazenar entradas em "dados" da seguinte maneira:
fonte
data = sys.stdin.read()
, sem o problema de concatenações de sequência repetidas.Leia a partir
sys.stdin
, mas para ler dados binários no Windows , você precisa ter cuidado extra, poissys.stdin
ele é aberto no modo de texto e ele será corrompido ao ser\r\n
substituído\n
.A solução é definir o modo como binário se o Windows + Python 2 for detectado e no Python 3 usar
sys.stdin.buffer
.fonte
Eu uso o método a seguir, ele retorna uma string de stdin (eu uso para a análise de json). Funciona com pipe e prompt no Windows (ainda não testado no Linux). Quando solicitado, duas quebras de linha indicam o fim da entrada.
fonte
O problema que tenho com solução
é que, se você não passar nenhum dado para o stdin, ele será bloqueado para sempre. É por isso que adoro esta resposta : verifique se há alguns dados sobre stdin primeiro e depois leia-os. Isto é o que acabei fazendo:
fonte
select
for chamada; ou você também pode enfrentar problemas se o stdin estiver conectado a um arquivo em uma mídia lenta (rede, CD, fita etc.). Você disse que "se você não passar nenhum dado para o stdin, ele será bloqueado para sempre". é um problema , mas eu diria que é um recurso . A maioria dos programas CLI (por exemplocat
) funciona dessa maneira, e espera-se que eles funcionem. EOF é a única coisa da qual você deve confiar para detectar o final da entrada.Eu tive alguns problemas ao fazer isso funcionar para a leitura de soquetes canalizados para ele. Quando o soquete foi fechado, ele começou a retornar uma string vazia em um loop ativo. Portanto, esta é minha solução (que eu testei apenas no Linux, mas espero que funcione em todos os outros sistemas)
Portanto, se você começar a ouvir em um soquete, ele funcionará corretamente (por exemplo, no bash):
E você pode chamá-lo com telnet ou apenas apontar um navegador para localhost: 12345
fonte
Em relação a este:
for line in sys.stdin:
Eu apenas tentei no python 2.7 (seguindo a sugestão de outra pessoa) para um arquivo muito grande, e não o recomendo, exatamente pelas razões mencionadas acima (nada acontece por um longo tempo).
Acabei com uma solução um pouco mais pitônica (e funciona em arquivos maiores):
Então eu posso executar o script localmente como:
fonte
sys.stdin
como argumento da linha de comando para o script.sys.stdin
como argumento da linha de comando para o script? Argumentos são sequências e fluxos são objetos semelhantes a arquivos, não são os mesmos.sys.stdin
é um arquivo-como objetoPara Python 3, isso seria:
Esta é basicamente uma forma simples de cat (1), pois não adiciona uma nova linha após cada linha. Você pode usar isso (depois de marcar o arquivo executável usando
chmod +x cat.py
:fonte
Existe o
os.read(0, x)
que lê xbytes de 0 que representa stdin. Esta é uma leitura sem buffer, com um nível mais baixo que o sys.stdin.read ()fonte
Ao usar o
-c
comando, de uma maneira complicada, em vez de ler ostdin
(e mais flexível em alguns casos), você também pode passar um comando de script de shell para o seu comando python colocando o comando de venda entre aspas entre parênteses, iniciado por$
sign.por exemplo
Contará o número de linhas do arquivo de histórico do goldendict.
fonte