Miksi `BrokenPipeError` riippuu johdettavan virran koosta?
On helmikuu 15, 2021 by admin Seuraava komentosarja herättää BrokenPipeError: [Errno 32] Broken pipe
, kun se ohjataan komentoon, kuten head
(paitsi jos pään rivien määrä ylittää Python-komentosarjan tulostamien rivien määrän).
for i in range(16386): print("")
$ python test-pipe.py | head -1 Traceback (most recent call last): File "test-pipe.py", line 2, in <module> print("") BrokenPipeError: [Errno 32] Broken pipe
Ymmärrykseni (lähettäjältä tämä vastaus ja vastaukset tähän kysymykseen ) ovat virheitä, jos putki suljetaan ennen Python-prosessin päättymistä kirjoittaminen sille.
Jos kuitenkin pienennän iteroidun alueen yhdellä arvoon 16385, virhe ei nouse (ei ole varma, onko tämä kynnys sama kaikilla koneilla, joten kokeile vain suurta ja pientä lukua lisääntyä). Aluksi ajattelin, että tämä saattaa liittyä putkipuskurin kokoon, mutta se on minulle 64 kt (M=0; while printf A; do >&2 printf "\r$((++M)) B"; done | sleep 999
-kohdan mukaan, joten se ei näytä olevan syy.
Miksi BrokenPipeError
esiintyminen riippuu syötettävän sisällön koosta?
Tämä tapahtuu Python 3.8.1: n kanssa Linux 5.4.15-arch1: ssä -1.
Kommentit
Vastaa
Miksi esiintyminenBrokenPipeError riippuu putkistojen koosta?
Koska useamman tavaran kirjoittaminen vie enemmän aikaa, ja putkilinjan oikea puoli voi kuolla, ennen kuin python on kirjoittanut sen. Jos python yrittää kirjoittaa enemmän kuin mahtuu putkipuskuriin, se estää ja antaa head -1
-lehdelle tarpeeksi aikaa poistua.
Koska head -1
kestää jonkin aikaa elää ja kuolla, python voi käyttää sitä aikaa kaikkien tavaroidensa kirjoittamiseen – jos se sopii putkipuskuriin – ja poistua onnistuneesti. Sitä on vaikea ennustaa, koska ydin voi vapaasti ajastaa putkilinjan molemmat puolet missä tahansa järjestyksessä, ja se voi viivästyttää head -1
-aloitteen aloittamista niin kauan kuin se pitää sopivana tai se voi lopeta se milloin tahansa.
>>> python3 -c "for i in range(50000): print("")" | sleep .01 Traceback (most recent call last): File "<string>", line 1, in <module> BrokenPipeError: [Errno 32] Broken pipe >>> python3 -c "for i in range(50000): print("")" | sleep .1 # OK!
Mutta jos python yrittää kirjoittaa enemmän tavaraa kuin putkeen mahtuu, se saa väistämättä EPIPE
tai SIGPIPE
lopulta riippumatta siitä kuinka paljon aikaa sillä on:
>>> python3 -c "for i in range(100000): print("")" | sleep 20 Traceback (most recent call last): File "<string>", line 1, in <module> BrokenPipeError: [Errno 32] Broken pipe
mutta se on minulle 64 kt … joten se ei näytä olevan syy.
Muista, että python käyttää täyttä puskurointia , kun lähtö ei ole pääte; se ei kirjoita rivi riviltä tai tavu tavulta, vaan jonkin kokoisilla paloilla:
>>> strace -s3 -e trace=write python3 -c "for i in range(50000): print("")" | sleep .3 write(1, "\n\n\n"..., 8193) = 8193 write(1, "\n\n\n"..., 8193) = 8193 write(1, "\n\n\n"..., 8193) = 8193 write(1, "\n\n\n"..., 8193) = 8193 write(1, "\n\n\n"..., 8193) = 8193 write(1, "\n\n\n"..., 8193) = 8193 write(1, "\n\n\n"..., 842) = 842 +++ exited with 0 +++
:
komennonhead -1
sijaan.python3 -c "for i in range(10000): print(i)" | : </dev/tcp/unix.stackexchange.com/https
. Jos tuplaat / kolminkertaistat alue, python, jolla on vika Broken Pipellä.