>  기사  >  백엔드 개발  >  사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!

사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!

coldplay.xixi
coldplay.xixi앞으로
2020-09-29 18:01:222033검색

사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!

print 함수는 우리 일상생활에서 가장 흔히 사용되는 함수임에는 틀림이 없습니다. 출력 형식을 지정하든, 디버깅을 위해 중간 변수를 출력하든, 에 나오는 함수는 거의 없습니다. print가 작업을 처리할 수 없습니다. print 函数是我们日常最常用的函数,无论是格式化输出还是打印中间变量进行调试,几乎没有 print 接不了的活儿。

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

坑从何来

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

사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!
点击并拖拽以移动

根据我们

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

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

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

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

类似这样:

사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!
点击并拖拽以移动

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

사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!
点击并拖拽以移动

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

它长大了, 也变丑了

사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!
点击并拖拽以移动

那我要你有何用?

사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!
点击并拖拽以移动

啥问题呢?

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

사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!
点击并拖拽以移动

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

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

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

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

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

하지만 지난번에 Ajiang은 인쇄에 속을 뻔했습니다.

피트는 어디에서 오는가

처음에는 명령줄 가젯 중 하나에 진행률 표시 기능을 추가하고 싶어서 스레딩 멀티스레딩을 구현하는 모듈로, 하나의 스레드는 실제 로직을 실행하는 데 사용되고 다른 스레드는 현재 진행 상황을 인쇄하는 데 사용됩니다. <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="사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!" ><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="사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!" ><figcaption></figcaption></figure><figure><figcaption>클릭하고 드래그하여 이동하세요</figcaption></figure><p>우리의 </p>🎜년 동안의 명령줄 사용 경험에 따르면 일반적으로 인쇄 진행 상황은 인라인으로 인쇄되며 Python의 <code>인쇄🎜 🎜 기본적으로 끝에 개행 문자가 인쇄되는데 이는 매우 보기 흉합니다. 🎜🎜다행히 print는 인쇄의 마지막 문자를 변경할 수 있는 인터페이스도 제공합니다. printend 매개변수를 지정하면 변경할 수 있습니다. 인쇄의 인쇄 결과입니다. 🎜🎜그래서 작업을 시작하고 진행 상황을 print("#", end="") code>로 인쇄하도록 print("#") 호출을 변경했습니다. 🎜🎜이와 유사: 🎜🎜사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!🎜🎜🎜🎜🎜클릭하고 드래그하여 이동하세요🎜🎜🎜그런 것 같지는 않지만 이번 변경에는 큰 문제가 있습니다. 진행 상황을 실시간으로 인쇄할 수 없다는 점입니다. 🎜🎜사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!🎜🎜🎜🎜🎜클릭해서 드래그하면 이동🎜🎜🎜즉, 프로그램 실행 중 하나씩 출력되어야 했던 # 숫자가 더 이상 순종적이지 않게 된 것입니다. 귀엽고 #이지만 전체 프로그램이 실행된 후 한꺼번에 콘솔에 출력됩니다. 🎜🎜성장했고 못생기기도 했습니다. 🎜🎜사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!🎜🎜🎜🎜🎜클릭하고 드래그하여 이동하세요🎜🎜🎜그럼 나한테 네가 필요한 게 뭐야? 🎜🎜사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!🎜🎜🎜🎜🎜클릭하여 드래그하여 이동하세요🎜🎜

문제가 무엇인가요?

🎜처음에 Ajiang은 멀티스레딩에 문제가 있다고 생각하여 자신의 다양한 추측을 "지원"하기 위해 어리석게도 여기저기에서 정보를 찾았습니다. 나중에 생각해보면 너무 어리석어서 이야기할 때 여전히 웃습니다. 이제🎜 🎜사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!🎜🎜🎜🎜🎜클릭하고 드래그하여 이동하세요🎜🎜🎜이 사건이 우리에게 주는 교훈은 절대 독선적이지 말고, 현실적으로 문제를 해결하고 모든 세부 사항을 겸손하게 대하라는 것입니다. . 🎜🎜사실 실시간 출력을 볼 수 없는 이유는 print의 끝 문자를 변경했기 때문입니다. 🎜🎜I/O 작업을 최소화하기 위해 Python에는 문자열 끝, 개행 문자 또는 버퍼가 강제로 새로 고쳐질 때 출력 문자를 최대한 캐시하는 메커니즘이 있습니다. 해당 스트림으로 즉시 출력됩니다. 🎜🎜——우리가 변경한 것은 print의 기본 개행 문자를 제거하는 것입니다. 따라서 원래 모든 print는 버퍼 새로 고침을 트리거했지만 이제는 버퍼 새로 고침을 트리거할 수 없습니다. 프로그램이 끝날 때까지. 🎜🎜자, 이제 문제가 무엇인지 알았으니 다시 정보를 찾기 시작했습니다. sys.stdout.flush가 강제로 표준 출력 버퍼 플러시를 트리거할 수 있다고 들었습니다. >print
그 후 sys.stdout.flush()가 즉시 추가되었습니다. 🎜🎜에? 정말 좋은가요? 🎜🎜🎜🎜🎜🎜🎜🎜클릭하고 드래그하여 이동하세요🎜🎜🎜이것들은 모두 지식 포인트입니다. 적어두고 시험에 응시하세요🎜
사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!
클릭하고 드래그하여 이동하세요.

print에 대한 공식 문서를 확인해 보세요. 프로토타입은 다음과 같습니다: print 的官方文档,其原型为:

사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!
点击并拖拽以移动

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

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

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

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

사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!
点击并拖拽以移动
사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!
点击并拖拽以移动

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

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

사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!
사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!
클릭하고 드래그하여 이동하세요
아래 설명에 따르면 Python의 print 출력이 버퍼링되는지 여부는 fileflush라는 두 가지 매개 변수에 따라 달라집니다.
sys.stdout와 같은 일부 파일 유형에는 버퍼링이 필요하지만 sys.stderr와 같은 다른 유형에는 버퍼링이 필요하지 않습니다. 사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!
flush 매개변수의 경우 값이 False(기본값)인 경우 버퍼링 여부는 값이 인 경우 <code>file에 따라 다릅니다. > True, 버퍼가 강제로 플러시됩니다.
예제 호출에서 print 호출을 수정해 보겠습니다.
사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!

클릭하고 드래그하여 이동

사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!

클릭하여 모바일로 드래그하세요

진행 상황을 실시간으로 인쇄할 수도 있습니다.

또한, 프로그램을 호출할 때 -u 옵션을 추가하는 방법이 있으며, 이를 통해 버퍼를 실시간으로 새로 고칠 수도 있습니다. 🎜🎜🎜🎜🎜🎜🎜🎜클릭하여 드래그 to move🎜 🎜🎜🎜🎜🎜🎜🎜🎜클릭하고 드래그하여 이동🎜🎜🎜물론 이 방법은 권장되지 않습니다. 결국 프로그램 사용자를 위한 사전 설정이 불가능하기 때문입니다. 🎜🎜요약🎜🎜이 글은 Ajiang의 함정에 대한 기록입니다. Python에서 소수의 사람들이 직면하게 될 이상한 문제를 기록합니다. 🎜🎜일반적으로, 진정한 Python 프로그래머가 되려면 단순히 기본 구문과 몇 가지 요령을 익히는 것만으로는 충분하지 않습니다. Python 자체에 대한 어느 정도 이해가 필요합니다. 🎜🎜결국, 자신의 검에 익숙하지 않은 검객이 어떻게 세상을 헤쳐 나갈 수 있겠습니까? 🎜🎜🎜관련 무료 학습 권장사항: 🎜python 비디오 튜토리얼🎜🎜🎜

위 내용은 사람들은 Python을 사용할 때 얼마나 많은 함정을 겪었습니까? 위험을 피하세요!의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.im에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제