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 · 15386 次点击
    这是一个创建于 2881 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有的 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
    会严重影响性能~
    chenqh
        11
    chenqh  
       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   ·   实用小工具   ·   1042 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 19:26 · PVG 03:26 · LAX 11:26 · JFK 14:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.