Python 中大量使用 print 会影响性能吗?

有的 Java 编程规范禁止使用 print 强制让用 logger 代替

不知道 python 是不是也一样的


Python 中大量使用 print 会影响性能吗?
35 回复

io 会影响性能的,但是使用 log 是为了更方便管理吧。。


会,但通常影响不大。print 本身是 I/O 操作,主要瓶颈在终端/控制台的渲染速度,而不是 Python 解释器。在循环里每秒打印成千上万次才会明显拖慢程序。如果真遇到性能问题,可以先把输出攒到列表或 StringIO 里,最后一次性打印。

简单说:别在关键循环里疯狂打印就行。

我就怕 println 是同步阻塞 而且没有缓存,来一个请求发一次

缓存是不可能的
有缓冲

print 好像是会同步阻塞的吧
感觉最能体现这一点的应该在网络延时高的情况下 ssh 进服务器跑 py 的时候,由于输出耗时长所以带大量 print 的方法的执行速度肯定会拖累下来

我想的应该就是缓冲 尴尬。。

io 本来速度就很慢,但是请问下使用 log 会比直接 print 快吗难道?

看你用哪种了,如果把 log 放到 redis 里用 pub,sub 来实现会好很多。

当然会,所以不到关键时刻,不要随便 print ,虽然 print 性能下降到原来几分之一很正常。

会严重影响性能~

如果并发高,logger 就少点咯,然而我没有并发

log 框架有异步的,减少 IO 次数,提高效率

>/dev/null 就不会太影响性能。

不懂 Python,不过原理差不多吧
虽然 print 和 logger 都一样是 io consume 的,不过很多 logger 是基于 ringbuffer 做的异步输出
另外还有线程安全的问题,Python 的 print 也是线程不安全的,你有加锁么…
另外如果用 print,你要把日志打印到文件,如果没有用第三方 log rotate 工具,日志会堆积…
堆积到磁盘满了,你想删除日志文件,还要等所有持有 inode 的进程都停掉文件才能被删除,不停止进程还没法清空磁盘

首先,你要有这样一个高并发的程序。

本质上应该还是把数组先保存在内存,之后在写入到磁盘吧?

不能这样,会有内存溢出的风险

两个耗时应该一样吧,如果是高并发,肯定 logger 好

为什么你的回复没有提醒?

log 有不同级别,可以关闭,可以替换内部实现, print 就很难拓展了

我觉得“大量使用 print ”会影响性能。因为“ print ”本来就是慢的(属于 IO ),我猜测它比写文件还要慢,所以会拖慢速度。

……
print 是往标准输出写数据,在 python 上应该是有缓冲
写日志一般调用的也是有缓冲的方法,同时写日志模块自己也会设计缓冲
你可以都理解成写文件
但是你都往一个文件里写的时候,并发高到阻塞就成为一个问题。
标准输出只有一个,文件可以有很多,但是磁盘的读写速度也是有限的。
——————————————
所以,你要考虑你程序的性质
一个简单的展示用 print 没什么问题
如果输出太快你看不过来,可能那时候还没触及你所谓的性能瓶颈,可能那时候瓶颈是人眼
如果你的程序是高并发程序,即使不触及瓶颈,你能保证看到所有你想要的输出吗?能保证以后查找问题的时候使用吗?

这么给你说吧:
python<br>a = 2**999999999999<br>
这一行代码不到一秒钟就可以计算完毕。
但是如果你加上一行
print(a)

那么你需要等几个小时才能看到有东西显示出来。

io 流很影响性能、、、

对。一般放到队列里。

等了十分钟也没计算完毕。。。

不能推荐大量使用的原因之一是非线程安全的


a = 2**9999999

我来说一个我前一段时间遇到的迷之 BUG 。
是一个 Django 的项目,还在开发阶段。之前一直在本地开发,那段时间把项目部署到测试服务器上。
我使用 django 自带的 web 服务器,用 (<a target="_blank" href="http://manage.py" rel="nofollow noopener">manage.py</a> runserver 0.0.0.0:8000 &gt; /dev/null &amp;) 来执行。
我访问我本地的网站,一直都正常。但访问服务器上的网站,有一些特定的页面, HTTP 请求始终不会结束。表现为网页能打开,但浏览器的小圈圈一直不会停。使用 curl 请求,能立刻获得页面完整内容,但脚本必须要等到超时才能结束。使用 ajax 调用,因为 http response 一直不结束,所以 ajax 成功的回调也无法执行,直到 http 超时才能得到一个 timeout 的错误。
我整理了问题出现的各种条件,直到我发现,只要我不关终端,问题就不会出现,关闭了终端,问题才有可能出现。我这才恍然大悟。
> 只重定向输出,不会重定向错误信息。我的那个命令会将输出丢弃,但错误信息仍然会打印到我当前的终端上。我在本地时, run 是在 IDE 的 Terminal 中执行的,只要我 IDE 不关闭,这个会话其实一直都在运行。用( ... &amp;)运行的命令是没有一个终端界面的, Django 中偶尔的错误信息和和 log 信息没有重定向也无法显示,会抛出到它的父终端来显示。当我关闭了 xshell 后,父会话结束了,这些输出没有任何人愿意认领,会堆积在输出缓存里,当输出缓存堆满,就被阻塞。 http 的结束符无法发送,前台浏览器就会阻塞。

跑题了。回到主题
不建议大量的 print 。在开发阶段,这些输出能够很好的帮助找到错误。但如果输出过多,则会干扰有用的信息。建议需要保留存档的使用专用的日志模块实现。调试则用 IDE 的 Debug run 。因为无论什么用途,都有比 print 更好的方案。

我的第一印象也是 py 这种单线程优先的语言, print 绝对会影响性能的吧?

print 多了是一定会的, print 使用的是字符设备, io 中最慢的一款。

单论写效率问题,一个是标准输出 1 ,一个是写文件,如果缓冲方式一样,效率是差别不大的。之所以建议 logger 而不是 print ,应该是方便日志管理,设置日志输出级别,多线程日志输出同步,以及玩异步写什么的。

不见得会有很大性能影响:
1. 真要高性能用 C ,或者 C 模块,别欺负 Python
2. 有 buffer ,而且写入 log 文件 buffer 比写终端要快,因为不是 linebuffer
推荐用 logging 是因为:
1. 不需要自己 format ,可以简单套模板
2. logging 会以行为单位,一次性写入,或者用锁。如果不这样的话多线程的 log 可能会撕裂
3. 尽管 logging 默认是写入文件,但是可以通过拓展 logger.emit(),轻松实现其他输出,比如输出到日志服务器。而 print 不可能扩展,也只能由外部程序捕捉输出文件再转发

说那么多有的没的,怎么不去看看 CPython 源码呢? https://hg.python.org/cpython/file/tip/Lib/logging/init.py

stdio is line buffered ,方便用户程序,这是 Linux 和很多操作系用的默认

buffered IO 怎么会慢,进 buffer 就是一次 memory copy

那你用 logging 输出一下 2*999999 试试?

用终端跑后台本来就是不对。说实话,我怀疑你关了终端你的后端已经被杀掉了。正经用 mod_wsgi 或者 gunicorn 根本没这档子事。正规用 systemd , systemd 会捕获所有输出,转给 journald

GIL 不锁 IO

print 会的话 logging 也会

影响比较大,我做处理一条一条文本记录的,读文本文件一行一条记录处理一下这样子
如果每一行处理结果都打印,整个程序可能要慢三分之一到一半的样子

回到顶部