Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: zu1234 18. 01. 2022, 15:33:18

Název: Python unbuffered print v cmd
Přispěvatel: zu1234 18. 01. 2022, 15:33:18
Po přenesení jednoho python programu z linuxu pod windows jsem zjistil divné chování příkazu print.
Aby se mi ve výstupech z programů (kdy se spojuje stout a stderr) nemíchalo
pořadí informací, zvykl jsem si nastavit python pomocí -u aby nebufferoval výstupy.

Když tento program spustím ve windows příkazové řádce
nedočkám správného konce výstupu - slova "konec":
#!/usr/bin/python3 -u
TXT = ""
for I in range(2000):
   TXT += f"{I:09d}\n"
TXT += "konec"
print(TXT)

Výstup skončí cca u hodnoty 1000.

Pokud na 1. řádku odstraním -u, začne se program
chovat správně, poslední slovo je 'konec'.
Popisované chování je stejné i když je na prvním řádku správnější:
#!python3 -u

Děje se tak jen pokud jde výstup přímo do terminálu a je nastaven zákaz bufferovaní.
Pokud jde výstup do souboru, nebo pokud odstraním '-u', funguje to správně.

Řešením asi bude vypínat bufferování až v programu, v závislosti na platformě:
if os.name == "posix":
   import io
   sys.stdout = io.TextIOWrapper(open(sys.stdout.fileno(), 'wb', 0), write_through=True)
   sys.stderr = io.TextIOWrapper(open(sys.stderr.fileno(), 'wb', 0), write_through=True)
Název: Re:Python unbuffered print v cmd
Přispěvatel: _Tomáš_ 18. 01. 2022, 15:55:19
píšeš o windowsu, ale spouštíš bash, přes co ho máš? cygwin? WSL?

Můžeš zkusit variantu s print("", flush=True)? Mám pocit, že to -u se ti správně nepřepíše, myslím, že by bylo vhodnější použít #!/usr/bin/env -S python3 -u
Název: Re:Python unbuffered print v cmd
Přispěvatel: zu1234 18. 01. 2022, 16:10:13
Je to spuštěno na prosté cmd windows příkazové řádce.
Linuxový shebang je tam proto, že se snažím do programů přenesených z linuxu nezasahovat.
Na problém to nemá vliv (jak ostatně uvádím).
Varianta s flush = True se chová stejně blbě:
#!python3 -u
TXT = ""
for I in range(2000):
   TXT += f"{I:09d}\n"
TXT += "konec"
print(TXT, flush = True)

Konec výstupu na terminál:
...
000000990
000000991
000000992
000000993
000000994
000000995
000000996
000000997
000000998
000000999
00
Název: Re:Python unbuffered print v cmd
Přispěvatel: _Tomáš_ 18. 01. 2022, 16:18:34
to vypadá na nějaké přetečení bufferu či jiné oříznutí, sice píšeš o unbuffered vypisování, ale tady vše uložíš nejprve do jednéj proměnné a pak vypíšeš najednou, jaký má tenhle test význam?

Odzkoušel jsem teď na čerstvě staženém python3.9 na Windows stanici, že unbuffered přes flush=True funguje. Windows ale není můj velký kamarád a moc ho nepoužívám, abych to znal do hloubky.
Název: Re:Python unbuffered print v cmd
Přispěvatel: zu1234 18. 01. 2022, 16:38:34
Nejedná se zbytečný test, ale ilustraci problému kdy například program, který
vypisuje strukturu tabulek databáze, na windows cmd terminálu skončí jakoby v polovině.
Zajímavé je, že tak děje při VYNUTÉM bufferování.
Název: Re:Python unbuffered print v cmd
Přispěvatel: tecka 19. 01. 2022, 00:07:52
Varianta bez cesty ani náhodou není správnější (ta je úplně blbě), Windows shebang vůbec nepodporuje a ani Python sám ho neinterpretuje (AFAIK). Takže se výsledky svých snah nepokoušej nějak interpretovat, protože v postupu nemáš žádnou logiku.
Název: Re:Python unbuffered print v cmd
Přispěvatel: _Tomáš_ 19. 01. 2022, 08:56:31
jakou verzi pythonu máš? Jak to spouštíš?

Koukám, že pokud na výstup zapisuješ unicode (či ascii) znaky, Windows tam má 64Kb buffer (ale očividně ne pro všechny případy https://docs.microsoft.com/en-us/windows/console/writeconsole?redirectedfrom=MSDN), to odpovídá i tomu co ti to vypsalo.

Pokud chceš zapsat libovolné množství dat, musíš zapisovat v binárním módu, tj. -u, to ti ale očividně nefunguje a něco děláš špatně.

Pak je tady další otázka, ono vůbec není bezpečné na consoly vypisovat binární výstup, to může vést k dost podstatné zranitelnosti. Nemůžeš prostě vypisovaný text rozsekat na jednotlivé části a printovat postupně? Co ten tvůj use case má za smysl?
Název: Re:Python unbuffered print v cmd
Přispěvatel: zu1234 19. 01. 2022, 09:45:18
Varianta bez cesty ani náhodou není správnější (ta je úplně blbě), Windows shebang vůbec nepodporuje a ani Python sám ho neinterpretuje (AFAIK). Takže se výsledky svých snah nepokoušej nějak interpretovat, protože v postupu nemáš žádnou logiku.
Z chování programu vyplývá že windows shebang je zpracováván, protože chování programu se mění podle toho zda shebang obsahuje '-u'
Název: Re:Python unbuffered print v cmd
Přispěvatel: _Tomáš_ 19. 01. 2022, 09:55:37
Varianta bez cesty ani náhodou není správnější (ta je úplně blbě), Windows shebang vůbec nepodporuje a ani Python sám ho neinterpretuje (AFAIK). Takže se výsledky svých snah nepokoušej nějak interpretovat, protože v postupu nemáš žádnou logiku.
Z chování programu vyplývá že windows shebang je zpracováván, protože chování programu se mění podle toho zda shebang obsahuje '-u'

Ne, windows a jeho příkazové řádky (cmd, powershell) shebang nepodporují. Otázka ale je, jak to vlastně spouštíš, jestli tam nemáš bash přes cygwin či nějak jinak.
Název: Re:Python unbuffered print v cmd
Přispěvatel: zu1234 19. 01. 2022, 09:57:14
jakou verzi pythonu máš? Jak to spouštíš?

Koukám, že pokud na výstup zapisuješ unicode (či ascii) znaky, Windows tam má 64Kb buffer (ale očividně ne pro všechny případy https://docs.microsoft.com/en-us/windows/console/writeconsole?redirectedfrom=MSDN), to odpovídá i tomu co ti to vypsalo.

Pokud chceš zapsat libovolné množství dat, musíš zapisovat v binárním módu, tj. -u, to ti ale očividně nefunguje a něco děláš špatně.

Pak je tady další otázka, ono vůbec není bezpečné na consoly vypisovat binární výstup, to může vést k dost podstatné zranitelnosti. Nemůžeš prostě vypisovaný text rozsekat na jednotlivé části a printovat postupně? Co ten tvůj use case má za smysl?
Python 3.9.1, W10 64bit
Příkaz print provádí konverzi kódování.
Problém vzniká při NEBUFFEROVANÉM výstupu.
Můj příspěvek není o tom že bych to neuměl nějak obejít (například stačí ponechat standartní buffered stav), ale o podivném chování unbuffered výstupu.
Název: Re:Python unbuffered print v cmd
Přispěvatel: ByCzech 19. 01. 2022, 17:44:17
Osobně si myslím, že problém je ve Windows console, která má vlastní buffer a než se stihnout vypsat všechna data z bufferu té console, tak program skončí a Windows výpis zastaví. Zkuste to samé mimo Windows.
Název: Re:Python unbuffered print v cmd
Přispěvatel: zu1234 21. 01. 2022, 09:51:21
Osobně si myslím, že problém je ve Windows console, která má vlastní buffer a než se stihnout vypsat všechna data z bufferu té console, tak program skončí a Windows výpis zastaví. Zkuste to samé mimo Windows.
Pokud jsem Vás dobře pochopil, tak vypnutí bufferovaní v pythonu pod windows/cmd je jako z louže pod okap? :-))
Ano, opravdu to tak vypadá.
Když jsem ale běh program prodloužil nějakým blastem za příkazem print, nemělo to vliv na (špatné) chování.

Na Debianu samozřejmě všechno v pořádku!
Název: Re:Python unbuffered print v cmd
Přispěvatel: _Tomáš_ 21. 01. 2022, 12:38:20
nedaří se mi tohle chování někde nasimulovat, i několika MB výstup dostanu celý. Můžeš popsat v čem a jak to spouštíš? Co zachytává ten výstup? Vypisuješ ho nebo někam ukládáš? Jakým příkazem spouštíš ten bash script?
Název: Re:Python unbuffered print v cmd
Přispěvatel: zu1234 25. 01. 2022, 10:20:33
Viz přílohy
Název: Re:Python unbuffered print v cmd
Přispěvatel: _Tomáš_ 25. 01. 2022, 13:55:21
a můžeš ukázat příkaz jak to přesně spouštíš? Protože cmd.exe prostě nerozumím syntaxi #! a stejně tak těžko budeš mít něco v cestě v /usr/bin/python3, když Windows používá písmena a zpětná lomítka. Chybí mi tady ještě ten jeden dílek do skládačky.

Na screenu je vidět gvim, to směřuje k cygwinu.

Problém totiž může být kdekoliv na cestě a nikoliv pouze ve Windows, tak je potřeba ověřit každou komponentu a zjistit tu, která se nechová podle očekávání nebo to ořezává.
Název: Re:Python unbuffered print v cmd
Přispěvatel: zu1234 25. 01. 2022, 16:17:07
V těch obrázcích je všechno, co se k tomu dá říct a taky
všechno co, jsem k tomu už několikrát napsal :-)
Tedy žádný cygwin. Prostě jen windowsy, jen gvim pro windowsy, jen příkazová řádka cmd a na ní jen x.py .
A to je celé. Připadám si jako čím dál zajímavější kouzelník :-)
Pořád někdo tvrdí že windowsy neumí #! . Je to nesmysl.
Podívete se na obrázky: program reaguje na to, zda v hashbang-u je nebo není -u .
Myslím že mezi samotným Pythonem-interpretem a zdrojákem v pythonu
je cosi, co se nainstaluje s Pythonem a jmenuje se Python Launcher.
Zadáním python na příkazové řádce se nespustí Python ale Microsoft store :-)
Na spuštění Python-interpretu musíte použít příkaz py .
Mluvím o Windows 10 (64bit) a Python 3.9.1 .
Název: Re:Python unbuffered print v cmd
Přispěvatel: Karmelos 25. 01. 2022, 17:35:54
Co je prosím přesně napsáno na příkazové řádce té konzole před výpisem 000000000?
A co se stane když to pustíte v powershelu?
Název: Re:Python unbuffered print v cmd
Přispěvatel: zu1234 25. 01. 2022, 20:33:09
Co je prosím přesně napsáno na příkazové řádce té konzole před výpisem 000000000?

To se nedá zjistit, protože pokud výstup přesměruji do souboru, začne se program chovat správně - výpis je kompletní.

A co se stane když to pustíte v powershelu?

Chování stejné - viz příloha
Název: Re:Python unbuffered print v cmd
Přispěvatel: Karmelos 25. 01. 2022, 21:11:56
Mě to dělá něco jiného - po spuštění skriptu >python pokus.py mi to vypisuje do té samé konzole nebo PS, ve kterém jsem to spustil. Neotvírá mi to novou.
Taky nemáte default znaky/font v tej konzoli, takže máte něco někde přenastavené. Víc netuším.
Název: Re:Python unbuffered print v cmd
Přispěvatel: _Tomáš_ 25. 01. 2022, 22:48:14
V těch obrázcích je všechno, co se k tomu dá říct a taky
všechno co, jsem k tomu už několikrát napsal :-)
Tedy žádný cygwin. Prostě jen windowsy, jen gvim pro windowsy, jen příkazová řádka cmd a na ní jen x.py .
A to je celé. Připadám si jako čím dál zajímavější kouzelník :-)
Pořád někdo tvrdí že windowsy neumí #! . Je to nesmysl.
Podívete se na obrázky: program reaguje na to, zda v hashbang-u je nebo není -u .
Myslím že mezi samotným Pythonem-interpretem a zdrojákem v pythonu
je cosi, co se nainstaluje s Pythonem a jmenuje se Python Launcher.
Zadáním python na příkazové řádce se nespustí Python ale Microsoft store :-)
Na spuštění Python-interpretu musíte použít příkaz py .
Mluvím o Windows 10 (64bit) a Python 3.9.1 .

To, že to spouštíš přes Python Launcher jsi předtím nenapsal, jsem vůbec netušil, že tenhle projekt ještě žije. V tom případě ale sám Python Launcher interpretuje ten #! a nikoliv Windows, ty to prostě neumí. Je možné, že právě on tam dělá ten problém ořezávání.

Můžeš zkusit to přímo spustit přes python.exe -u py3.py?

Název: Re:Python unbuffered print v cmd
Přispěvatel: zu1234 26. 01. 2022, 15:21:39
Pokud je stejný script puštěn přímo pomocí python.exe tak:

1) Není zohleňováno nastavení '-u' z 1. řádku: '#!/usr/bin/python3 -u'
Jinak řečeno: to že je to jindy zohledněno je práce Python Launcheru - py.exe .

2) Python dělá popisovanou chybu že nevytlačí celý řetězec pokud je
použito volání 'python.exe -u' , nebo pokud je vypnutí bufferování
uděláno v programu.

Název: Re:Python unbuffered print v cmd
Přispěvatel: Karmelos 26. 01. 2022, 19:19:36
Omlouvám se za možná stupidní dotaz, k čemu to je, anebo, čemu to teda vadí?
Tak prostě nepoužívejte to -u?
Možná nahlásit jako bug ?
Název: Re:Python unbuffered print v cmd
Přispěvatel: zu1234 26. 01. 2022, 20:51:55
Není to stupidní dotaz.
Bral jsem to jako upozornění python-veřejnosti na podivnost.
Po zkušenosti s celou touto diskuzí a s přihlédnutím ke svým
komunikačním dovednostem v cizím jazyku se nedám na nějaký
bug report.
Sorry. Třeba se najde někdo schopnější.
Název: Re:Python unbuffered print v cmd
Přispěvatel: uwe.filter 27. 01. 2022, 11:11:47
Po zkušenosti s celou touto diskuzí a s přihlédnutím ke svým
komunikačním dovednostem v cizím jazyku se nedám na nějaký
bug report.
Sorry. Třeba se najde někdo schopnější.

To je myslím docela škoda, pokud se opravdu jedná o bug. Přinejmenším by to byla zajímavá příležitost zkusit ty komunikační dovednosti trošku vylepšit. Z vlastní zkušenosti bych doporučil ten popis bugu strukturovat pro lepší srozumitelnost asi takhle:

Název: Re:Python unbuffered print v cmd
Přispěvatel: Karmelos 27. 01. 2022, 11:37:55
Není to stupidní dotaz.
Bral jsem to jako upozornění python-veřejnosti na podivnost.
Po zkušenosti s celou touto diskuzí a s přihlédnutím ke svým
komunikačním dovednostem v cizím jazyku se nedám na nějaký
bug report.
Sorry. Třeba se najde někdo schopnější.


Díky za odpověď.
Jak píše uwe, zkus to naformulovat jako bug sem, a třeba se to někomu podaří replikovat a ten bug pak může nahlásit on... Předpokládám, že tak to i bylo na začátku míněno...
Název: Re:Python unbuffered print v cmd
Přispěvatel: zu1234 10. 02. 2022, 19:23:13
Pokusil jsem se to shrnout:

Windows 10, verze 21h2, 64bit:

c:\prj\py3>type x.py
TXT = ""
for I in range(3000):
        TXT += f"{I:09d}\n"
print(TXT)
print("Konec")

c:\prj\py3>C:\Users\uzivatel\AppData\Local\Programs\Python\Python39\python.exe x.py
...
000002988
000002989
000002990
000002991
000002992
000002993
000002994
000002995
000002996
000002997
000002998
000002999

Konec

c:\prj\py3>C:\Users\uzivatel\AppData\Local\Programs\Python\Python39\python.exe -u x.py
...
000000737
000000738
000000739
000000740
000000741
000000742
000000743
000000744
000000745
000000746
000000747
000000748
000000749

Konec

c:\prj\py3>  :(

Název: Re:Python unbuffered print v cmd
Přispěvatel: listoper 10. 02. 2022, 22:20:40
Nebude to tohle: https://github.com/python/cpython/pull/26678
zda se ze to jeste neni zamergovany
Název: Re:Python unbuffered print v cmd
Přispěvatel: zu1234 11. 02. 2022, 09:20:44
Nebude to tohle: https://github.com/python/cpython/pull/26678
zda se ze to jeste neni zamergovany

Tak jsem doufal, že jsem objevil Ameriku, ale mám zpoždění rok a půl.
To Cimrman je alespoň míjel ve dveřích!
:-))