Python 中大量使用 print 会影响性能吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
whx20202
V2EX    Python

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

  •  
  •   whx20202 2017-02-04 09:23:58 +08:00 16004 次点击
    这是一个创建于 3250 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    不知道 python 是不是也一样的

    34 条回复    2021-01-26 10:34:13 +08:00
    virusdefender
        1
    virusdefender  
       2017-02-04 09:27:06 +08:00 via iPhone
    io 会影响性能的,但是使用 log 是为了更方便管理吧。。
    whx20202
        2
    whx20202  
    OP
       2017-02-04 09:36:28 +08:00
    我就怕 println 是同步阻塞 而且没有缓存,来一个请求发一次
    ryd994
        3
    ryd994  
       2017-02-04 09:40:37 +08:00 via Android
    缓存是不可能的
    有缓冲
    techmoe
        4
    techmoe  
       2017-02-04 09:43:38 +08:00 via Android
    print 好像是会同步阻塞的吧
    感觉最能体现这一点的应该在网络延时高的情况下 ssh 进服务器跑 py 的时候,由于输出耗时长所以带大量 print 的方法的执行速度肯定会拖累下来
    whx20202
        5
    whx20202  
    OP
       2017-02-04 09:44:02 +08:00
    @ryd994 我想的应该就是缓冲 尴尬。。
    chy373180
        6
    chy373180  
       2017-02-04 09:45:07 +08:00
    会的
    misaka19000
        7
    misaka19000  
       2017-02-04 09:46:13 +08:00 via Android
    io 本来速度就很慢,但是请问下使用 log 会比直接 print 快吗难道?
    robinlovemaggie
        8
    robinlovemaggie  
       2017-02-04 09:49:08 +08:00
    @misaka19000 看你用哪种了,如果把 log 放到 redis 里用 pub,sub 来实现会好很多。
    Neveroldmilk
        9
    Neveroldmilk  
       2017-02-04 09:56:13 +08:00
    当然会,所以不到关键时刻,不要随便 print ,虽然 print 性能下降到原来几分之一很正常。
    knktc
        10
    knktc  
       2017-02-04 10:03:27 +08:00
    会严重影响性能~
    simple2025
        11
    simple2025  
       2017-02-04 10:28:36 +08:00
    如果并发高,logger 就少点咯,然而我没有并发
    D3EP
        12
    D3EP  
       2017-02-04 10:37:24 +08:00 via Android
    @misaka19000 log 框架有异步的,减少 IO 次数,提高效率
    est
        13
    est  
       2017-02-04 10:38:57 +08:00
    >/dev/null 就不会太影响性能。
    slixurd
        14
    slixurd  
       2017-02-04 10:42:25 +08:00   1
    不懂 Python,不过原理差不多吧
    虽然 print 和 logger 都一样是 io consume 的,不过很多 logger 是基于 ringbuffer 做的异步输出
    另外还有线程安全的问题,Python 的 print 也是线程不安全的,你有加锁么......
    另外如果用 print,你要把日志打印到文件,如果没有用第三方 log rotate 工具,日志会堆积...
    堆积到磁盘满了,你想删除日志文件,还要等所有持有 inode 的进程都停掉文件才能被删除,不停止进程还没法清空磁盘
    lbp0200
        15
    lbp0200  
       2017-02-04 10:45:30 +08:00 via Android   1
    首先,你要有这样一个高并发的程序。
    misaka19000
        16
    misaka19000  
       2017-02-04 10:49:16 +08:00
    @D3EP 本质上应该还是把数组先保存在内存,之后在写入到磁盘吧?
    lbp0200
        17
    lbp0200  
       2017-02-04 10:59:28 +08:00
    @misaka19000 不能这样,会有内存溢出的风险
    ke1e
        18
    ke1e  
       2017-02-04 11:02:05 +08:00 via Android
    两个耗时应该一样吧,如果是高并发,肯定 logger 好
    misaka19000
        19
    misaka19000  
       2017-02-04 11:08:04 +08:00
    @lbp0200 为什么你的回复没有提醒?
    guyskk
        20
    guyskk  
       2017-02-04 11:14:59 +08:00 via Android
    log 有不同级别,可以关闭,可以替换内部实现, print 就很难拓展了
    liuzhiyong
        21
    liuzhiyong  
       2017-02-04 11:40:36 +08:00
    我觉得“大量使用 print ”会影响性能。因为“ print ”本来就是慢的(属于 IO ),我*猜测*它比写文件还要慢,所以会拖慢速度。
    vincenttone
        22
    vincenttone  
       2017-02-04 12:04:11 +08:00   1
    ……
    print 是往标准输出写数据,在 python 上应该是有缓冲
    写日志一般调用的也是有缓冲的方法,同时写日志模块自己也会设计缓冲
    你可以都理解成写文件
    但是你都往一个文件里写的时候,并发高到阻塞就成为一个问题。
    标准输出只有一个,文件可以有很多,但是磁盘的读写速度也是有限的。

    所以,你要考虑你程序的性质
    一个简单的展示用 print 没什么问题
    如果输出太快你看不过来,可能那时候还没触及你所谓的性能瓶颈,可能那时候瓶颈是人眼
    如果你的程序是高并发程序,即使不触及瓶颈,你能保证看到所有你想要的输出吗?能保证以后查找问题的时候使用吗?
    billion
        23
    billion  
       2017-02-04 12:19:21 +08:00   2
    这么给你说吧:
    ```python
    a = 2**999999999999
    ```
    这一行代码不到一秒钟就可以计算完毕。
    但是如果你加上一行
    print(a)

    那么你需要等几个小时才能看到有东西显示出来。
    ovear
        24
    ovear  
       2017-02-04 12:20:34 +08:00
    io 流很影响性能、、、
    D3EP
        25
    D3EP  
       2017-02-04 12:52:14 +08:00
    @misaka19000 对。一般放到队列里。
    misaka19000
        26
    misaka19000  
       2017-02-04 13:24:56 +08:00
    @billion 等了十分钟也没计算完毕。。。
    IanPeverell
        27
    IanPeverell  
       2017-02-04 13:45:23 +08:00
    不能推荐大量使用的原因之一是非线程安全的
    tkisme
        28
    tkisme  
       2017-02-04 14:22:36 +08:00
    @misaka19000
    a = 2**9999999
    jininij
        29
    jininij  
       2017-02-04 15:22:03 +08:00   1
    我来说一个我前一段时间遇到的迷之 BUG 。
    是一个 Django 的项目,还在开发阶段。之前一直在本地开发,那段时间把项目部署到测试服务器上。
    我使用 django 自带的 web 服务器,用 `(manage.py runserver 0.0.0.0:8000 > /dev/null &)` 来执行。
    我访问我本地的网站,一直都正常。但访问服务器上的网站,有一些特定的页面, HTTP 请求始终不会结束。表现为网页能打开,但浏览器的小圈圈一直不会停。使用 curl 请求,能立刻获得页面完整内容,但脚本必须要等到超时才能结束。使用 ajax 调用,因为 http response 一直不结束,所以 ajax 成功的回调也无法执行,直到 http 超时才能得到一个 timeout 的错误。
    我整理了问题出现的各种条件,直到我发现,只要我不关终端,问题就不会出现,关闭了终端,问题才有可能出现。我这才恍然大悟。
    > 只重定向输出,不会重定向错误信息。我的那个命令会将输出丢弃,但错误信息仍然会打印到我当前的终端上。我在本地时, run 是在 IDE 的 Terminal 中执行的,只要我 IDE 不关闭,这个会话其实一直都在运行。用`( ... &)`运行的命令是没有一个终端界面的, Django 中偶尔的错误信息和和 log 信息没有重定向也无法显示,会抛出到它的父终端来显示。当我关闭了 xshell 后,父会话结束了,这些输出没有任何人愿意认领,会堆积在输出缓存里,当输出缓存堆满,就被阻塞。 http 的结束符无法发送,前台浏览器就会阻塞。

    跑题了。回到主题
    不建议大量的 print 。在开发阶段,这些输出能够很好的帮助找到错误。但如果输出过多,则会干扰有用的信息。建议需要保留存档的使用专用的日志模块实现。调试则用 IDE 的 Debug run 。因为无论什么用途,都有比 print 更好的方案。
    yuchting
        30
    yuchting  
       2017-02-04 16:08:40 +08:00 via Android
    我的第一印象也是 py 这种单线程优先的语言, print 绝对会影响性能的吧?
    linbiaye
        31
    linbiaye  
       2017-02-04 18:01:44 +08:00
    print 多了是一定会的, print 使用的是字符设备, io 中最慢的一款。
    kingddc314
        32
    kingddc314  
       2017-02-04 21:17:11 +08:00 via Android
    单论写效率问题,一个是标准输出 1 ,一个是写文件,如果缓冲方式一样,效率是差别不大的。之所以建议 logger 而不是 print ,应该是方便日志管理,设置日志输出级别,多线程日志输出同步,以及玩异步写什么的。
    ryd994
        33
    ryd994  
       2017-02-04 23:26:19 +08:00   3
    不见得会有很大性能影响:
    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

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

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

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

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

    @yuchting GIL 不锁 IO

    @linbiaye print 会的话 logging 也会
    DF5206A
        34
    DF5206A  
       2021-01-26 10:34:13 +08:00
    影响比较大,我做处理一条一条文本记录的,读文本文件一行一条记录处理一下这样子
    如果每一行处理结果都打印,整个程序可能要慢三分之一到一半的样子
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3947 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 04:12 PVG 12:12 LAX 20:12 JFK 23:12
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86