Zanurkuj w Pythonie/Standardowy strumień wejścia, wyjścia i błędów: Różnice pomiędzy wersjami
Usunięta treść Dodana treść
Zdzichobot (dyskusja | edycje) zamiana {{Nawigacja|Python|->{{Nawigacja|Zanurkuj w Pythonie| [[Python/->[[../ |
poprawki |
||
Linia 1:
{{Podświetl|py}}▼
== Standardowy strumień wejścia, wyjścia i błędów==
Użytkownicy Uniksa są już prawdopodobnie zapoznani z koncepcją standardowego wejścia, standardowego wyjścia i standardowego strumienia błędów. Ten podrozdział jest dla pozostałych osób.
Standardowe wyjście i strumień błędów (powszechnie używana skrócona forma to ''stdout'' i ''stderr'') są strumieniami danych wbudowanymi do każdego systemu Unix. Kiedy coś
'''Przykład 10.8. Wprowadzenie do ''stdout'' i ''stderr'''''▼
{{Python/Przykład
|tekst=
>>> for i in range(3):
... print '
{{samp|Nurkujemy
Nurkujemy
Nurkujemy}}
>>> import sys
>>> for i in range(3):
... sys.stdout.write('
{{samp|NurkujemyNurkujemyNurkujemy}}
>>> for i in range(3):
... sys.stderr.write('
{{samp|NurkujemyNurkujemyNurkujemy}}
# Jak zobaczyliśmy w
# <
# W tym prostym przypadku <
}}
Zarówno <tt>stdout</tt> i <tt>stderr</tt> są ''obiektami pliko-podobnymi'', a które omawialiśmy w Podrozdziale 10.1, “Abstrakcyjne źródła wejścia”, lecz te są tylko do zapisu. Nie posiadają one metody <tt>read</tt>, tylko <tt>write</tt>. Jednak nadal są one ''obiektami pliko-podobnymi'' i możemy do nich przypisać inny obiekt pliku lub ''obiekt pliko-podobny'', aby przekierować ich wyjście.▼
▲Zarówno <
'''Przykład 10.9. Przekierowywanie wyjścia'''▼
{{Python/Przykład
|tekst=
[you@localhost kgp]$ python stdout.py
{{samp|Nurkujemy}}
[you@localhost kgp]$ cat out.log
{{samp|Ta wiadomość będzie logowana i nie zostanie wypisana na wyjście}}
(W Windowsie,
<pre>
#-*- coding: utf-8 -*-
</pre>
# To zostanie wypisane w interaktywnym oknie IDE (lub w terminalu, jeśli skrypt został uruchomiony z linii poleceń).
# Zawsze, zanim przekierujemy standardowe wyjście, przypisujemy gdzieś <
# Otwieramy plik do zapisu. Jeśli plik nie istnieje, zostanie utworzony. Jeśli istnieje, zostanie nadpisany.
# Całe późniejsze wyjście zostanie przekierowane do pliku, który właśnie otworzyliśmy.
# Zostanie to wypisane tylko do pliku <tt>out.log</tt>; nie będzie widoczne w oknie IDE lub w terminalu.
# Przywracamy <
# Zamykamy plik <tt>out.log</tt>.
}}
Dodajmy, że w wypisywanym łańcuchu znaków użyliśmy polskich znaków, a ponieważ nie skorzystaliśmy z [[../Łańcuchy znaków i unikod|unikodu]], więc napis ten zostanie wypisany w takiej samej postaci, w jakiej został zapisany w pliku Pythona (czyli wiadomość zostanie zapisana w kodowaniu <tt>utf-8</tt>). Gdybyśmy skorzystali z unikodu, musielibyśmy wyraźnie zakodować ten napis do jakiegoś kodowania za pomocą [[../Praca z unikodem#przy-3.36|metody <code>encode</code>]], ponieważ Python nie wie, z jakiego kodowania chce korzystać utworzony przez nas plik (plik <tt>out.log</tt> przypisany do zmiennej <code>stdout</code>).
Przekierowywanie standardowego strumienia błędów (<tt>stderr</tt>) działa w ten sam sposób, wykorzystując <tt>sys.stderr</tt>, zamiast <tt>sys.stdout</tt>.▼
▲Przekierowywanie standardowego strumienia błędów (
'''Przykład 10.10. Przekierowywanie informacji o błędach'''▼
{{Python/Przykład
|tekst=
[you@localhost kgp]$ python stderr.py
[you@localhost kgp]$ cat error.log
{{samp|<nowiki>Traceback (most recent line last):
<pre>
#-*- coding: utf-8 -*-
▲ #stderr.py
</pre>
# Otwieramy plik <tt>error.log</tt>, gdzie chcemy przechowywać informacje debugujące.
# Przekierowujemy standardowy strumień błędów, dzięki przypisaniu obiektu nowo otwartego pliku do <
# Rzucamy wyjątek. Zauważmy, że na ekranie wyjściowym nic nie zostanie wypisane. Wszystkie informacje ''traceback'' zostały zapisane w <tt>error.log</tt>.
# Zauważmy także, że nie zamknęliśmy jawnie pliku <tt>error.log</tt>, a nawet nie przypisaliśmy do <
}}
Ponieważ powszechnie wypisuje się informacje o błędach na standardowy strumień błędów, Python posiada skrótową składnie, która można wykorzystać do bezpośredniego przekierowywania wyjścia.
{{Python/Przykład
|tekst=
>>> print '
{{samp|wchodzimy do funkcji}}
>>> import sys
>>> print >> sys.stderr, '
wchodzimy do funkcji
# Ta skrótowa składnia wyrażenia <
}}
Z innej strony, standardowe wejścia jest obiektem pliku tylko do odczytu i reprezentuje dane przechodzące z niektórych wcześniejszych programów. Prawdopodobnie nie jest to zrozumiałe dla klasycznych użytkowników Mac OS-a lub nawet dla użytkowników Windows, którzy nie mieli za wiele do czynienia z linią poleceń MS-DOS-a. Działa to w ten sposób, że konstruujemy ciąg poleceń w jednej linii, w taki sposób, że to co jeden program wypisuje na wyjście, następny w tym ciągu traktuje jako wejście. Pierwszy program prosto wypisuje wszystko na standardowe wyjście (bez korzystania ze specjalnych przekierowań, wykorzystuje normalną instrukcję <
|10.12 |tekst=
<span>[you@localhost kgp]$ python kgp.py -g binary.xml #(1)
{{samp|01100111}}
[you@localhost kgp]$ cat binary.xml #(2)
{{samp|<nowiki><?xml version="1.0"?>
<nowiki>[you@localhost kgp]$ cat binary.xml | python kgp.py -g - #(3) (4)</nowiki>
{{samp|10110001}}</span>
# Jak zobaczyliśmy w [[../Przetwarzanie XML-a#przy-9.4|podrozdziale 9.1,
# Dzięki temu po prostu wypiszemy całą zawartość pliku <tt>binary.xml</tt>. (Użytkownicy Windowsa powinni wykorzystać polecenie <tt>type</tt> zamiast <tt>cat</tt>.)
# Polecenie to wypisuje zawartość pliku
# Zamiast określać modułu (np. <tt>binary.xml</tt>), dajemy "-", który każe naszemu skryptowi wczytać gramatykę ze standardowego wejścia, zamiast z określonego pliku na dysku. (Więcej o tym, w jaki sposób to się dzieje w następnym przykładzie.) Zatem efekt będzie taki sam, jak w pierwszym poleceniu, gdzie bezpośrednio określamy plik gramatyki, ale tutaj zwróćmy uwagę na rozszerzone możliwości. Zamiast wywoływać <tt>cat binary.xml</tt>, moglibyśmy uruchomić skrypt, który by dynamicznie generował gramatykę, a następnie mógłby ją doprowadzić do naszego skryptu. Dane mogłyby przyjść skądkolwiek: z bazy danych, innego skryptu generującego gramatykę lub jeszcze inaczej. Zaletą tego jest to, że nie musimy zmieniać w żaden sposób
}}
Więc w jaki sposób skrypt "wie", żeby czytać ze standardowego wejścia, gdy plik gramatyki to "-"? To nie jest żadna magia; to tylko właśnie prosty kod.
{{Python/Przykład
|tekst=
<pre>
def
if source == "-":
return sys.stdin
[... ciach ...]▼
# Jest to funkcja <tt>openAnything</tt> z <tt>toolbox.py</tt>, którą wcześniej badaliśmy w podrozdziale 10.1, "Abstrakcyjne źródła wejścia”. Wszystko, co musimy zrobić, to dodanie trzech linii kodu na początku, aby sprawdzić, czym źródłem nie jest "-"; jeśli tak, to zwracamy <tt>sys.stdin</tt>. Naprawdę, to tylko tyle! Pamiętasz, <tt>stdin</tt> jest ''obiektem pliko-podobnym'' z metodą read, więc pozostałą część kodu (w <tt>kgp.py</tt>, gdzie wywołujemy funkcję <tt>openAnything</tt>) w żaden sposób nie zmieniamy.▼
</pre>
▲# Jest to funkcja <
}}
<noinclude>
{{Nawigacja|Zanurkuj w Pythonie|
[[../Abstrakcyjne źródła wejścia
[[../Buforowanie odszukanego węzła
}}
▲{{Podświetl|py}}
</noinclude>
|