Por que não apenas
files = sys.argv[1:]
if not files:
files = ["/dev/stdin"]
for file in files:
f = open(file)
...
Eu tenho alguns scripts Python por aí, e estou trabalhando para reescrevê-los. Eu tenho o mesmo problema com todos eles.
Não é óbvio para mim como escrever os programas para que eles se comportem como ferramentas unix adequadas.
Porque isso
$ cat characters | progname
e isso
$ progname characters
deve produzir o mesmo resultado.
A coisa mais próxima que consegui encontrar em Python foi a biblioteca fileinput. Infelizmente, eu não vejo como reescrever meus scripts Python, todos com esta aparência:
#!/usr/bin/env python
# coding=UTF-8
import sys, re
for file in sys.argv[1:]:
f = open(file)
fs = f.read()
regexnl = re.compile('[^\s\w.,?!:;-]')
rstuff = regexnl.sub('', fs)
f.close()
print rstuff
A biblioteca fileinput processa stdin se houver um stdin e processa um arquivo se houver um arquivo. Mas itera em linhas simples.
import fileinput
for line in fileinput.input():
process(line)
Eu realmente não entendo isso. Eu acho que se você está lidando com arquivos pequenos, ou se você não está fazendo muito com os arquivos, isso pode parecer óbvio. Mas, para os meus propósitos, isso torna muito mais lento do que simplesmente abrir o arquivo inteiro e lê-lo em uma string, como acima.
Atualmente, corro o script acima como
$ pythonscript textfilename1 > textfilename2
Mas eu quero ser capaz de executá-lo (e seus irmãos) em canos, como
$ grep pattern textfile1 | pythonscript | pythonscript | pythonscript > textfile2
Verifique se um nome de arquivo é fornecido como argumento ou leia-o em sys.stdin
.
Algo parecido com isto:
if sys.argv[1]:
f = open(sys.argv[1])
else:
f = sys.stdin
É semelhante à resposta de Mikel, exceto pelo fato de usar o módulo sys
. Eu acho que se eles tiverem lá, deve ser por uma razão ...
Minha maneira preferida de fazê-lo é ... (e isso é tirado de um pequeno e simpático blog sobre Linux chamado Harbinger's Hollow )
#!/usr/bin/env python
import argparse, sys
parser = argparse.ArgumentParser()
parser.add_argument('filename', nargs='?')
args = parser.parse_args()
if args.filename:
string = open(args.filename).read()
elif not sys.stdin.isatty():
string = sys.stdin.read()
else:
parser.print_help()
A razão pela qual eu gostei disso é que, como diz o blogueiro, ele apenas envia uma mensagem tola se acidentalmente chamado sem entrada. Ele também se encaixa muito bem em todos os meus scripts Python existentes que eu os modifiquei para incluí-lo.
files=sys.argv[1:]
for f in files or [sys.stdin]:
if isinstance(f, file):
txt = f.read()
else:
txt = open(f).read()
process(txt)
Estou usando essa solução e funciona como um encanto. Na verdade, estou usando em um script de script unaccent que diminui o tamanho e remove os acentos de uma determinada string
argument = sys.argv[1:] if len(sys.argv) > 1 else sys.stdin.read()
Acho que a melhor hora em que vi essa solução foi aqui .
Tags python text-processing stdout pipe stdin