Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!

coldplay.xixi
Freigeben: 2020-10-14 17:41:01
nach vorne
2058 Leute haben es durchsucht

Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!

Es besteht kein Zweifel, dass die Funktion print die am häufigsten verwendete Funktion in unserem täglichen Leben ist, egal ob es sich um die Formatierung der Ausgabe oder das Drucken von Zwischenvariablen zum Debuggen handelt, es gibt fast nichts, was ist print kann nicht funktionieren. print 函数是我们日常最常用的函数,无论是格式化输出还是打印中间变量进行调试,几乎没有 print 接不了的活儿。

但是上一次阿酱就差点被 print 给坑了。

坑从何来

最初是想要为自己的一个命令行小工具增加一个进度显示功能,于是用了 threading 模块来实现多线程,一个线程用于执行实际的逻辑,另一个线程用于打印当前进度。

Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!
点击并拖拽以移动

根据我们

多年 使用命令行的经验,一般打印进度都是在行内打印,而Python的 print

则会默认在结尾打印一个换行符,这就十分不美了。

不过好在, print 也提供了接口来改变打印的末尾字符,通过指定 printend 参数,即可改变 print 的打印结果。

所以我就哼哧哼哧地开干了,把打印进度的 print("#") 调用改为 print("#", end="")

类似这样:

Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!
点击并拖拽以移动

哪成想,这么一改却出了大问题:进度没法实时打印了。

Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!
点击并拖拽以移动

也就是说,本来应该在程序执行期间,挨个打印出来的 # 号不再是听话的、可爱的 # 号了,而是在整个程序执行完成之后一次性输出到控制台中。

它长大了, 也变丑了

Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!
点击并拖拽以移动

那我要你有何用?

Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!
点击并拖拽以移动

啥问题呢?

一开始阿酱以为是多线程出了问题,傻乎乎地到处找资料来“佐证”自己的各种猜测——事后想来实在太傻了,以至于现在说起还是会哈哈哈

Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!
点击并拖拽以移动

这件事给我们的教训就是: 千万不要自以为是,而应踏踏实实地解决问题,虚心对待每个细节 。

实际上,之所以我们看不到实时的输出,就是因为我们改变了 print 的结尾字符。

为了尽量减少I/O操作,Python存在一个这样的机制:尽量将输出字符缓存起来,当遇到字符串结束、换行符或强制刷新缓冲区时,才会一次性将缓冲区的内容输出到相应的流中。

——而我们改掉的地方,就是把 print 默认的换行符去掉了,所以原本每一个 print 都会触发一次缓冲区刷新,变成了现在一直触发不了缓冲区刷新,直到程序结束触发一次。

好嘛,知道了啥问题,我们又吭哧吭哧找资料,听说 sys.stdout.flush 可以强制触发标准输出缓冲区的刷新,于是在 print 后面,紧跟着又加上了 sys.stdout.flush()

Aber letztes Mal ließ sich Ajiang fast von print täuschen.

Woher kommt die Grube

Anfangs wollte ich einem meiner Befehlszeilen-Gadgets eine Fortschrittsanzeigefunktion hinzufügen, also habe ich threading Modul zur Implementierung von Multithreading. Ein Thread wird zum Ausführen der eigentlichen Logik und der andere Thread zum Drucken des aktuellen Fortschritts verwendet. <figure><img class="lazyload" src="https://img.php.cn/upload/article/000/000/052/e81d361fe9c2aab616d404b5cdf741d3-12.png" data- style="max-width:90%" data- style="max-width:90%" alt="Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!" ><img class="lazyload" src="https://img.php.cn/upload/article/000/000/052/00378eb73c929c1c9646673ec2efcc73-0.png" data- style="max-width:90%" data-height=" 600" alt="Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!" ><figcaption></figcaption></figure><figure><figcaption>Klicken und ziehen, um zu verschieben</figcaption></figure><p>Nach unserer </p>🎜 jahrelangen Erfahrung in der Verwendung der Befehlszeile wird der Druckfortschritt im Allgemeinen inline gedruckt, und Pythons <code>print🎜 🎜 druckt am Ende standardmäßig ein Zeilenumbruchzeichen, was sehr unansehnlich ist. 🎜🎜Aber glücklicherweise bietet print auch eine Schnittstelle zum Ändern des letzten Zeichens des Drucks. Durch Angabe des end-Parameters von print können Sie Änderungen vornehmen print. 🎜🎜Also habe ich angefangen und den print("#")-Aufruf zum Drucken des Fortschritts in print("#", end="") code> geändert. 🎜🎜Ähnlich wie hier: 🎜🎜Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!🎜🎜🎜🎜🎜Klicken und ziehen, um zu verschieben🎜🎜🎜Ich glaube nicht, aber diese Änderung hat ein großes Problem: Der Fortschritt kann nicht in Echtzeit gedruckt werden. 🎜🎜Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!🎜🎜🎜🎜🎜Klicken und ziehen, um zu verschieben🎜🎜🎜Mit anderen Worten, die #-Nummern, die während der Ausführung des Programms einzeln gedruckt werden sollten, sind nicht mehr gehorsam und nettes #, wird aber sofort nach der Ausführung des gesamten Programms an die Konsole ausgegeben. 🎜🎜Es ist erwachsen geworden und hässlich geworden. 🎜🎜Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!🎜🎜🎜🎜🎜Zum Bewegen klicken und ziehen🎜🎜🎜Wozu brauche ich dich dann? 🎜🎜Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!🎜🎜🎜🎜🎜Klicken und ziehen, um zu verschieben🎜🎜

Was ist das Problem?

🎜Zuerst dachte Ajiang, es gäbe ein Problem mit Multi-Threading, also suchte sie törichterweise überall nach Informationen, um ihre verschiedenen Vermutungen zu „stützen“ – als sie später darüber nachdachte, war es so dumm, dass sie immer noch lacht, wenn sie darüber spricht es jetzt🎜 🎜Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!🎜🎜🎜🎜🎜Zum Bewegen klicken und ziehen🎜🎜🎜Die Lektion, die uns dieser Vorfall lehrt, ist: Seien Sie niemals selbstgerecht, sondern lösen Sie Probleme auf bodenständige Weise und gehen Sie mit jedem Detail mit Demut um . 🎜🎜Eigentlich können wir die Echtzeitausgabe nicht sehen, weil wir das Endzeichen von print geändert haben. 🎜🎜Um E/A-Vorgänge zu minimieren, verfügt Python über einen Mechanismus, der die Ausgabezeichen so weit wie möglich zwischenspeichert, wenn das Ende der Zeichenfolge, ein Zeilenumbruchzeichen oder der Puffer erzwungen wird, den Inhalt des Puffers zu aktualisieren wird sofort in den entsprechenden Stream ausgegeben. 🎜🎜——Was wir geändert haben, ist, das Standard-Neuzeilenzeichen von print zu entfernen, sodass ursprünglich jeder print eine Pufferaktualisierung auslösen würde, die nun zu „Jetzt kann die Pufferaktualisierung nicht ausgelöst werden“ wurde bis das Programm endet. 🎜🎜Okay, da wir nun wissen, wo das Problem liegt, haben wir erneut nach Informationen gesucht. Wir haben gehört, dass sys.stdout.flush das Leeren des Standardausgabepuffers erzwingen kann, also in print Danach wurde sofort sys.stdout.flush() hinzugefügt. 🎜🎜Äh? Ist es wirklich gut? 🎜🎜🎜🎜🎜🎜🎜🎜Zum Bewegen klicken und ziehen🎜🎜🎜Das sind alles Wissenspunkte, notieren Sie sie und machen Sie den Test🎜
Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!
Zum Verschieben klicken und ziehen

Schauen wir uns die offizielle Dokumentation für print an, deren Prototyp ist: print 的官方文档,其原型为:

Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!
点击并拖拽以移动

根据其下的描述,Python中 print 的输出是否进行缓冲,取决于两个参数: fileflush

file 的类型有的需要缓冲,比如 sys.stdout ;而有的则不需要缓冲,比如 sys.stderr

对于 flush 参数,当其值为 False (默认)时,是否缓冲依赖 file ;而当其值为 True 时,则会强制刷新缓冲区。

我们把示例调用中的 print 调用修改一下:

Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!
点击并拖拽以移动
Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!
点击并拖拽以移动

同样可以实现进度的实时打印。

此外,还有一种方法,在调用程序时增加一个 -u

Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!
Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!
Zum Verschieben klicken und ziehen
Laut der Beschreibung unten hängt es von zwei Parametern ab, ob die Ausgabe von print in Python gepuffert wird: file und flush.
Einige Arten von Dateien erfordern eine Pufferung, wie z. B. sys.stdout, während andere keine Pufferung erfordern, wie z. B. sys.stderr. Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!
Wenn der Wert des Parameters flush False (Standard) ist, hängt die Frage, ob gepuffert werden soll, von der Datei file ab > True
, das Leeren des Puffers wird erzwungen. Ändern wir den print-Aufruf im Beispielaufruf:
Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!

Zum Verschieben klicken und ziehen

Wie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!

Klicken und ziehen Sie auf Mobile

kann auch das Drucken des Fortschritts in Echtzeit realisieren.

Darüber hinaus gibt es eine Möglichkeit, beim Aufrufen des Programms eine Option -u hinzuzufügen, mit der auch eine Echtzeitaktualisierung des Puffers erreicht werden kann: 🎜🎜🎜🎜🎜🎜🎜🎜Klicken und ziehen zum Verschieben🎜 🎜🎜🎜🎜🎜🎜🎜🎜Klicken und ziehen zum Verschieben🎜🎜🎜Diese Methode ist natürlich nicht zu empfehlen, schließlich können keine Voreinstellungen für den Benutzer des Programms vorgenommen werden. 🎜🎜Zusammenfassung🎜🎜Dieser Artikel ist eine Aufzeichnung der Fallstricke von Ajiang. Er beschreibt ein seltsames Problem in Python, auf das nur wenige Menschen stoßen werden. 🎜🎜Wenn Sie ein echter Python-Programmierer werden möchten, reicht es im Allgemeinen nicht aus, nur die grundlegende Syntax und einige Tricks zu beherrschen. Sie müssen immer noch ein gewisses Verständnis von Python selbst haben. 🎜🎜Wie kann ein Schwertkämpfer schließlich durch die Welt navigieren, wenn er nicht mit seinem eigenen Schwert vertraut ist? 🎜🎜🎜Verwandte kostenlose Lernempfehlungen: 🎜Python-Video-Tutorial🎜🎜🎜

Das obige ist der detaillierte Inhalt vonWie viele Fallstricke sind bei der Verwendung von Python aufgetreten? Gefahren vermeiden!. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:juejin.im
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage