Próbuję wykonać niektóre z golfowych wyzwań kodowych , ale wszystkie wymagają wkładu stdin
. Jak mogę to uzyskać w Pythonie?
1470
Możesz użyć fileinput
modułu:
import fileinput
for line in fileinput.input():
pass
fileinput
przejdzie przez wszystkie linie na wejściu określone jako nazwy plików podane w argumentach wiersza poleceń lub standardowe wejście, jeśli nie podano argumentów.
Uwaga: line
będzie zawierać znak nowej linii; aby go usunąć użyjline.rstrip()
Można to zrobić na kilka sposobów.
sys.stdin
jest obiektem podobnym do pliku, do którego możesz wywoływać funkcjeread
lubreadlines
jeśli chcesz wszystko przeczytać lub chcesz wszystko przeczytać i automatycznie podzielić je na nową linię . (Musiszimport sys
to zrobić, aby zadziałało).Jeśli chcesz, aby skłonić użytkownika do wejścia, można użyć
raw_input
w Pythonie 2.x i tylkoinput
w Pythonie 3.Jeśli chcesz po prostu przeczytać opcje wiersza polecenia, możesz uzyskać do nich dostęp za pośrednictwem listy sys.argv .
Prawdopodobnie okaże się ten artykuł na Wikibook I / O w Pythonie , aby być użytecznym odniesienia, jak również.
źródło
Zauważ, że będzie to zawierać znak nowej linii na końcu. Aby usunąć nowy wiersz na końcu, użyj
line.rstrip()
jak powiedział @brittohalloran.źródło
\r\n
zakończeniami liniiPython ma również wbudowane funkcje
input()
iraw_input()
. Zobacz dokumentację Pythona w części Funkcje wbudowane .Na przykład,
lub
źródło
Oto z Learning Python :
W systemie Unix możesz to przetestować, wykonując coś takiego:
W systemie Windows lub DOS:
źródło
print(sum(chunk.count('\n') for chunk in iter(partial(sys.stdin.read, 1 << 15), '')))
. patrzwc-l.py
cat
tutaj jest zbędne. Prawidłowe wywołanie dla systemów uniksowych topython countlines.py < countlines.py
.readlines()
. Obiekty plików mają być iterowane bez zmaterializowania wszystkich danych w pamięci.Możesz użyć:
sys.stdin
- Obiekt podobny do pliku - wywołaniesys.stdin.read()
do odczytu wszystkiego.input(prompt)
- przekazać opcjonalny monit o wyjście, odczytuje ze standardowego wejścia do pierwszej nowej linii, którą usuwa. Musiałbyś to robić wielokrotnie, aby uzyskać więcej linii, na końcu wejścia podnosi EOFError. (Prawdopodobnie nie jest świetny do gry w golfa.) W Pythonie 2 tak jestrawinput(prompt)
.open(0).read()
- W Pythonie 3 wbudowana funkcjaopen
akceptuje deskryptory plików (liczby całkowite reprezentujące zasoby IO systemu operacyjnego), a 0 to deskryptor plikustdin
. Zwraca obiekt podobny do plikusys.stdin
- prawdopodobnie najlepszy wybór do gry w golfa. W Pythonie 2 jest toio.open
.open('/dev/stdin').read()
- podobny doopen(0)
, działa na Python 2 i 3, ale nie na Windows (lub nawet Cygwin).fileinput.input()
- zwraca iterator po liniach we wszystkich plikach wymienionych wsys.argv[1:]
lub stdin, jeśli nie podano. Użyj jak''.join(fileinput.input())
.Oba
sys
ifileinput
oczywiście muszą zostać zaimportowane.Szybkie
sys.stdin
przykłady kompatybilne z Python 2 i 3, Windows, UnixTrzeba tylko
read
odsys.stdin
, na przykład, jeśli dane rur do stdin:Widzimy, że
sys.stdin
jest w domyślnym trybie tekstowym:przykład pliku
Powiedzmy, że masz plik,
inputs.txt
możemy go zaakceptować i zapisać ponownie:Dłuższa odpowiedź
Oto kompletne, łatwe do odtworzenia demo, wykorzystujące dwie metody, wbudowaną funkcję
input
(użycieraw_input
w Pythonie 2) isys.stdin
. Dane są niezmodyfikowane, więc przetwarzanie nie jest wykonywane.Na początek stwórzmy plik dla danych wejściowych:
Korzystając z kodu, który już widzieliśmy, możemy sprawdzić, czy utworzyliśmy plik:
Oto pomoc
sys.stdin.read
z Python 3:Wbudowana funkcja
input
(raw_input
w Pythonie 2)Wbudowana funkcja
input
odczytuje ze standardowego wejścia do nowej linii, która jest usuwana (uzupełniającaprint
, która domyślnie dodaje nową linię). Dzieje się tak, dopóki nie otrzyma EOF (End Of File), w którym to momencie podnosi sięEOFError
.Oto, w jaki sposób możesz używać
input
w Pythonie 3 (lubraw_input
w Pythonie 2) do czytania ze stdin - dlatego tworzymy moduł Pythona, który nazywamy stdindemo.py:Wydrukujmy go ponownie, aby upewnić się, że jest zgodny z naszymi oczekiwaniami:
Znów
input
czyta aż do nowej linii i zasadniczo usuwa ją z linii.print
dodaje nową linię. Tak więc, gdy obaj modyfikują dane wejściowe, ich modyfikacje są anulowane. (Więc są one wzajemnie uzupełnieniem).A kiedy
input
dostaje znak końca pliku, podnosi EOFError, który ignorujemy, a następnie wychodzimy z programu.A w systemie Linux / Unix możemy przesyłać z cat:
Lub możemy po prostu przekierować plik ze standardowego wejścia:
Możemy również wykonać moduł jako skrypt:
Oto pomoc dotycząca wbudowanego
input
Pythona 3:sys.stdin
Tutaj tworzymy skrypt demo przy użyciu
sys.stdin
. Skutecznym sposobem na iterację obiektu podobnego do pliku jest użycie obiektu podobnego do pliku jako iteratora. Uzupełniającą metodą zapisu na standardowe wyjście z tego wejścia jest po prostu użyciesys.stdout.write
:Wydrukuj go ponownie, aby upewnić się, że wygląda poprawnie:
I przekierowanie danych wejściowych do pliku:
Grał w golfa w polecenie:
Deskryptory plików dla gry w golfa
Ponieważ deskryptory plików dla
stdin
istdout
są odpowiednio 0 i 1, możemy również przekazać je doopen
Pythona 3 (nie 2, i zauważ, że nadal potrzebujemy „w” do zapisu na standardowe wyjście).Jeśli to zadziała w twoim systemie, zgoli więcej postaci.
Python 2 również to
io.open
robi, ale import zajmuje dużo więcej miejsca:Adresowanie innych komentarzy i odpowiedzi
Jeden komentarz sugeruje
''.join(sys.stdin)
grę w golfa, ale w rzeczywistości jest on dłuższy niż sys.stdin.read () - a ponadto Python musi utworzyć dodatkową listę w pamięci (takstr.join
działa, gdy nie jest podana lista) - dla kontrastu:Najlepsza odpowiedź sugeruje:
Ponieważ jednak
sys.stdin
implementuje interfejs API pliku, w tym protokół iteratora, jest to dokładnie to samo:Inna odpowiedź to sugeruje. Pamiętaj tylko, że jeśli zrobisz to w tłumaczu, musisz to zrobić Ctrl- djeśli korzystasz z systemu Linux lub Mac, lub Ctrl- zw systemie Windows (po Enter), aby wysłać znak końca pliku do procesu. Również ta odpowiedź sugeruje
print(line)
- co dodaje'\n'
do końca - użycieprint(line, end='')
zamiast tego (jeśli w Pythonie 2 będziesz potrzebowaćfrom __future__ import print_function
).Prawdziwym przypadkiem użycia
fileinput
jest odczytywanie w szeregu plików.źródło
Odpowiedź zaproponowana przez innych:
jest bardzo prosty i pytoniczny, ale należy zauważyć, że skrypt zaczeka na EOF, zanim zacznie iterować na liniach wejściowych.
Oznacza to, że
tail -f error_log | myscript.py
linie nie będą przetwarzane zgodnie z oczekiwaniami.Prawidłowy skrypt dla takiego przypadku użycia to:
AKTUALIZACJA
Z komentarzy zostało wyjaśnione, że tylko w Pythonie może występować buforowanie, tak że w końcu czekasz na wypełnienie bufora lub EOF przed wydaniem wywołania drukowania.
źródło
for line in sys.stdin:
Wzór nie czekać na EOF. Ale jeśli testujesz na bardzo małych plikach, odpowiedzi mogą zostać buforowane. Przetestuj z większą ilością danych, aby zobaczyć, że odczytuje wyniki pośrednie.print line
nie budzi się w 3.1.3, aleprint(line)
tak.for line in sys.stdin:
nie „blokuje do EOF”. W Pythonie 2 występuje błąd odczytu z wyprzedzeniem, który opóźnia linie do momentu zapełnienia odpowiedniego bufora. Jest to problem buforowania niezwiązany z EOF. Aby obejść ten problem, użyjfor line in iter(sys.stdin.readline, ''):
(użyjio.open()
do zwykłych plików). Nie potrzebujesz go w Pythonie 3.Spowoduje to wyświetlenie echa standardowego wejścia na standardowe wyjście:
źródło
Opierając się na wszystkich anwersach
sys.stdin
, możesz również zrobić coś takiego jak poniżej, aby odczytać z pliku argumentu, jeśli istnieje co najmniej jeden argument, i w przeciwnym razie powróć do standardowego wejścia:i użyj go jako jednego z nich
lub
lub nawet
To sprawi, że Twój skrypt Pythona zachowuje się podobnie jak wiele programów GNU / Unix, takich jak
cat
,grep
ised
.źródło
argparse
jest łatwym rozwiązaniemPrzykład zgodny z wersją 2 i 3 Pythona:
Możesz uruchomić ten skrypt na wiele sposobów:
1. Korzystanie
stdin
lub krócej, zastępując
echo
przez tutaj ciąg :2. Za pomocą argumentu nazwy pliku
3. Używanie
stdin
specjalnej nazwy pliku-
źródło
add_argument('--in'
a następnie potokować do skryptu i dodać--in -
do wiersza polecenia. PSin
nie jest bardzo dobrą nazwą dla zmiennej / atrybutu.in
nie jest tylko złą nazwą zmiennej, jest nielegalna.args.in.read()
podniesie błąd InvalidSyntax z powoduin
zarezerwowanego słowa kluczowego. Można po prostu zmienić nazwę, abyinfile
polubić python argparse docs: docs.python.org/3/library/…Poniższy układ kodu pomoże ci (odczyta wszystkie stdin blokujące do
EOF
, w jednym ciągu):źródło
Jestem zdumiony, że nikt dotąd nie wspomniał o tym hacku:
w python2 możesz porzucić
set()
połączenie, ale wyraziłoby to w obu kierunkachźródło
readlines
tego podziału na linie, a potemjoin
znowu? Możesz po prostu napisaćprint(sys.stdin.read())
write
zwracaNone
, a ustawiony rozmiar nigdy nie byłby większy niż 1 (=len(set([None]))
)Spróbuj tego:
i sprawdź to za pomocą:
źródło
Możesz czytać ze standardowego wejścia, a następnie przechowywać dane wejściowe w „danych” w następujący sposób:
źródło
data = sys.stdin.read()
bez problemu z powtarzającymi się łączeniami łańcuchów.Czytaj z
sys.stdin
, ale aby odczytać dane binarne w systemie Windows , musisz zachować szczególną ostrożność, ponieważsys.stdin
jest on otwarty w trybie tekstowym i spowoduje uszkodzenie jego\r\n
zastąpienia\n
.Rozwiązaniem jest ustawienie trybu na binarny, jeśli wykryty zostanie system Windows + Python 2, a także w przypadku języka Python 3
sys.stdin.buffer
.źródło
Korzystam z następującej metody, zwraca ciąg ze stdin (używam go do parsowania json). Działa z potokiem i monitami w systemie Windows (jeszcze nie testowany w systemie Linux). Po wyświetleniu monitu dwa podziały linii wskazują koniec wprowadzania.
źródło
Problem z rozwiązaniem
polega na tym, że jeśli nie przekażesz żadnych danych do standardowego wejścia, zostanie ono zablokowane na zawsze. Dlatego uwielbiam tę odpowiedź : najpierw sprawdź, czy są jakieś dane dotyczące standardowego wejścia, a następnie je przeczytaj. Tak właśnie skończyłem:
źródło
select
zostanie wywołane; lub możesz napotkać problemy, jeśli stdin jest podłączony do pliku na wolnym nośniku (sieć, płyta CD, taśma itp.). Powiedziałeś, że „jeśli nie przekażesz żadnych danych do standardowego wejścia, zablokuje ono na zawsze”. jest problemem , ale powiedziałbym, że to funkcja . Większość programów CLI (np.cat
) Działa w ten sposób i oczekuje się tego. EOF jest jedyną rzeczą, na której powinieneś polegać, aby wykryć koniec danych wejściowych.Miałem pewne problemy z uruchomieniem tego do odczytu przez podłączone do niego gniazda. Kiedy gniazdo zostało zamknięte, zaczęło zwracać pusty ciąg w aktywnej pętli. To jest moje rozwiązanie (które testowałem tylko w systemie Linux, ale mam nadzieję, że zadziała we wszystkich innych systemach)
Więc jeśli zaczniesz nasłuchiwać na gnieździe, będzie działało poprawnie (np. W bash):
Możesz to nazwać telnetem lub po prostu skierować przeglądarkę na localhost: 12345
źródło
Odnośnie tego:
for line in sys.stdin:
Właśnie wypróbowałem go w Pythonie 2.7 (zgodnie z sugestią kogoś innego) dla bardzo dużego pliku i nie polecam go, właśnie z wyżej wymienionych powodów (nic się nie dzieje przez długi czas).
Skończyło się na nieco bardziej pythonowym rozwiązaniu (i działa na większych plikach):
Następnie mogę uruchomić skrypt lokalnie jako:
źródło
sys.stdin
do skryptu argument wiersza polecenia.sys.stdin
skrypt jako argument wiersza poleceń? Argumenty są łańcuchami, a strumienie są obiektami podobnymi do plików, nie są takie same.sys.stdin
to plikopodobnym obiektuDla Pythona 3 byłoby to:
Jest to w zasadzie prosta forma cat (1), ponieważ nie dodaje nowej linii po każdej linii. Możesz użyć tego (po oznaczeniu pliku wykonywalnego za pomocą
chmod +x cat.py
:źródło
Jest taki,
os.read(0, x)
który odczytuje xbytes od 0, co reprezentuje standardowe wejście. Jest to odczyt niebuforowany, bardziej niski poziom niż sys.stdin.read ()źródło
Podczas korzystania z
-c
polecenia, jako trudnego sposobu, zamiast czytaćstdin
(a w niektórych przypadkach bardziej elastyczny) można przekazać polecenie skryptu powłoki również do polecenia python, umieszczając polecenie sprzedaży w cudzysłowie w nawiasach rozpoczynanych$
znakiem.na przykład
Policzy to liczbę linii z pliku historii goldendict.
źródło