Mam kilka skryptów Pythona i pracuję nad ich napisaniem. Mam ten sam problem ze wszystkimi.
Nie jest dla mnie oczywiste, jak pisać programy, aby działały jak właściwe narzędzia uniksowe.
Ponieważ to
$ cat characters | progname
i to
$ progname characters
powinien generować ten sam wynik.
Najbliższą rzeczą, jaką mogłem znaleźć w Pythonie, była biblioteka fileinput. Niestety tak naprawdę nie widzę, jak przepisać moje skrypty w języku Python, z których wszystkie wyglądają tak:
#!/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
Biblioteka fileinput przetwarza stdin, jeśli istnieje stdin, i przetwarza plik, jeśli istnieje plik. Ale iteruje się po pojedynczych liniach.
import fileinput
for line in fileinput.input():
process(line)
Naprawdę tego nie rozumiem. Myślę, że jeśli masz do czynienia z małymi plikami lub jeśli nie robisz wiele z plikami, może to wydawać się oczywiste. Ale dla moich celów jest to znacznie wolniejsze niż po prostu otwieranie całego pliku i wczytywanie go w ciąg znaków, jak powyżej.
Obecnie uruchamiam skrypt powyżej jak
$ pythonscript textfilename1 > textfilename2
Ale chcę być w stanie uruchomić go (i jego braci) w fajkach
$ grep pattern textfile1 | pythonscript | pythonscript | pythonscript > textfile2
Odpowiedzi:
Dlaczego nie tylko
źródło
sys.stdin
powinien być używany zamiast tego, ponieważ jest bardziej przenośny niż zakodowana na stałe ścieżka do pliku.sys.stdin
należy zamiast tego użyć, jak mówi Piotrsys.stdin
jest plikiem i jest już otwarty i nie można go zamknąć. Niemożliwe jest obsługiwanie jak argument pliku bez przeskakiwania przez obręcze.f
lub użyć menedżera kontekstu, potrzebujesz czegoś bardziej złożonego. Zobacz moją nową odpowiedź jako alternatywę.Sprawdź, czy nazwa pliku jest podana jako argument, czy też odczytana z
sys.stdin
.Coś takiego:
Jest podobny do odpowiedzi Mikela, tyle że korzysta z
sys
modułu. Sądzę, że jeśli go tam mają, to musi być jakiś powód ...źródło
"open(/dev/stdin")
sięsys.stdin
.if len(sys.argv)>1:
zamiast wif sys.argv[1]:
przeciwnym razie otrzymasz błąd poza zakresem indeksuMoim preferowanym sposobem na to okazuje się ... (i pochodzi z ładnego małego linuksowego bloga Harbinger's Hollow )
Powodem, dla którego podobało mi się to najbardziej, jest to, jak mówi bloger, że po prostu wywołuje głupią wiadomość, jeśli przypadkowo zostanie wywołana bez udziału. Tak dobrze wpasowuje się we wszystkie moje istniejące skrypty Pythona, że zmodyfikowałem je wszystkie, aby je uwzględnić.
źródło
isatty
i ratowanie nie jest zgodne z filozofią filtrów uniksowych.isatty
brodawki, obejmuje to użyteczny i ważny grunt, którego nie znaleziono w innych odpowiedziach, więc dostaje moją opinię.źródło
/dev/stdin
były niedostępne na wszystkich moich systemach.Korzystam z tego rozwiązania i działa jak urok. Właściwie używam w skrypcie calle unaccent, który zamienia małe litery i usuwa akcenty z danego ciągu
Chyba pierwszy raz, kiedy zobaczyłem, że to rozwiązanie jest tutaj .
źródło
Jeśli twój system nie ma
/dev/stdin
lub potrzebujesz bardziej ogólnego rozwiązania, możesz wypróbować coś bardziej skomplikowanego, na przykład:źródło
-
. :)