Como eu faço programas python se comportarem como ferramentas unix apropriadas?

20

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
    
por ixtmixilix 04.09.2012 / 12:53

5 respostas

9

Por que não apenas

files = sys.argv[1:]
if not files:
    files = ["/dev/stdin"]

for file in files:
    f = open(file)
    ...
    
por 04.09.2012 / 15:37
10

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 ...

    
por 04.09.2012 / 17:16
3

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.

    
por 08.09.2012 / 14:12
2
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)
    
por 12.12.2016 / 18:15
0

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 .

    
por 02.06.2018 / 12:01