V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
gaayyy
V2EX  ›  程序员

Python 中如何一个 print 语句同时输出到屏幕且记录到文件里

  •  
  •   gaayyy · 2017-09-06 22:40:02 +08:00 · 21792 次点击
    这是一个创建于 2616 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有一个第三方提供的脚本,一直在用,里面很多功能也封装的很好。唯一的缺憾就是他没有使用 log 模块,全部是 print 语句输出。

    现在老板想把所有 print 的输出全部实时的保存到一个文本文件中,又不能影响现有的屏幕输出,感觉比较困难。

    我试过用管道重定向:python cudaCFD.py > result.txt 发现只有在最后程序全部退出的时候才会把输出一次性写入到这个 result.txt 文件里面,而且这个方法也不能同时在屏幕的命令行中输出。

    希望各位 python 大佬指导一下,谢谢。

    23 条回复    2021-02-28 09:36:00 +08:00
    Trim21
        1
    Trim21  
       2017-09-06 22:40:52 +08:00
    覆写一下 print 函数
    0ZXYDDu796nVCFxq
        2
    0ZXYDDu796nVCFxq  
       2017-09-06 22:44:00 +08:00 via iPhone   ❤️ 1
    tee 命令
    a87150
        3
    a87150  
       2017-09-06 22:47:21 +08:00
    def pl(x):
    print(x)
    log(x)
    misaka19000
        4
    misaka19000  
       2017-09-06 22:48:25 +08:00   ❤️ 3
    NoAnyLove
        5
    NoAnyLove  
       2017-09-06 22:51:32 +08:00
    #4 的 Monkey patch 很巧妙,赞一个
    misaka19000
        6
    misaka19000  
       2017-09-06 22:51:59 +08:00   ❤️ 1
    虽然 V 站的编辑器很烂,还是把代码放上来吧
    ```python
    import sys


    class Logger(object):
    def __init__(self, filename="Default.log"):
    self.terminal = sys.stdout
    self.log = open(filename, "a")

    def write(self, message):
    self.terminal.write(message)
    self.log.write(message)

    def flush(self):
    pass


    sys.stdout = Logger("yourlogfilename.txt")
    print("Hello world !") # this is should be saved in yourlogfilename.txt
    ```
    gaayyy
        7
    gaayyy  
    OP
       2017-09-06 22:52:47 +08:00
    @Trim21
    @a87150
    不太希望动这个 print 函数,有的 print 的参数还不太一样,萌新不敢随便操作。

    @gstqc
    目测这个能解决问题,谢谢大佬

    最后纠正一点,那个 python cudaCFD.py > result.txt 不是最后一次性输出的,而是每满 4k 字节就写一次文件,我第一次操作输出不满 4k 所以得到的是个空的文件。
    gaayyy
        8
    gaayyy  
    OP
       2017-09-06 22:55:00 +08:00
    @misaka19000
    大佬的实现方法目测很优雅,however,大佬的英语比较渣,this should be saved in xxx, 你写多了一个 is
    flaneurse
        9
    flaneurse  
       2017-09-06 22:55:08 +08:00
    with open('file', 'wa') as f:,这里不确定要不要覆盖原文件还是添加新的输出
    print(result, file=f)
    print(result)
    Python2 的话,导入下__future__
    mxi1
        10
    mxi1  
       2017-09-06 22:57:46 +08:00
    在代码里面,尽量用 Logger,少用 print。
    PythonAnswer
        11
    PythonAnswer  
       2017-09-06 23:00:56 +08:00
    logging 是解决方案。
    gaayyy
        12
    gaayyy  
    OP
       2017-09-06 23:01:26 +08:00
    @mxi1 第三方提供的,科学计算用的,写的人不是专业的程序员,但是确实是需要这个东西来算,算法什么的都在里面,一堆矩阵运算全部在里面,不敢动。。。
    Osk
        13
    Osk  
       2017-09-06 23:03:02 +08:00   ❤️ 1
    楼主的问题很好解决,任一即可:
    python -u xxx.py
    export PYTHONUNBUFFERED=y ; xxx.py
    PYTHONUNBUFFERED=y xxx.py

    再配合 tee 就 ok 啦
    gaayyy
        14
    gaayyy  
    OP
       2017-09-06 23:07:28 +08:00
    @misaka19000 再请教一下大佬,如果按照你这个 class,需要在最后调用一下 flush 函数么?是不是要 flush 一下才会写入到文件?
    oott123
        15
    oott123  
       2017-09-07 09:02:14 +08:00 via Android
    tee 呗
    python xxx.py | tee log.txt
    不需要改一行代码
    xiaozizayang
        16
    xiaozizayang  
       2017-09-07 09:07:06 +08:00
    print("hello", file= open("./1.txt", 'a'))
    fluyy
        17
    fluyy  
       2017-09-07 13:54:15 +08:00 via iPhone
    用 logger 啊,定义输出到文件和控制台,我就是这么搞得
    gouchaoer
        18
    gouchaoer  
       2017-09-07 17:35:39 +08:00   ❤️ 1
    python test.py 2>&1 | tee -a $log_file
    就这么简单,非侵入式
    gouchaoer
        19
    gouchaoer  
       2017-09-07 17:38:57 +08:00
    都写了那么多 print 了,怎么改成 logger 啊
    我给你推荐一门语言 javascript,那个函数随便你改
    Osk
        20
    Osk  
       2017-09-07 23:10:32 +08:00
    回复用 管道+tee 的朋友来踩坑了。

    楼主应该是被 python 的 stdout 缓冲坑了,直接 | tee 或者 > 重定向到文件 这样信息输出不是“实时”的,只有等 buffer 满了才会输出,中途 ctrl+c 中断了甚至会丢失一些输出。运行 python 时关闭缓冲就可以了,不需要改代码,毕竟一个个 print 去修改太麻烦,万一第三方模块中有黑魔法就坑大了。
    gaayyy
        21
    gaayyy  
    OP
       2017-09-08 21:37:50 +08:00
    @Osk 是的,要满 4k 才写入文件,这个当时直接重定向就发现了。。。 感谢大佬的详细解释。

    @gouchaoer 感谢大佬指点,2>&1 是把 stderr 也重定向到 stdout 吧。Linux 下面的小工具是真心好用,不过我们这套东西有时候还要在 windows 下面用,毕竟 nvidia 的官配是 windows 平台。JS 我这种萌新不适合,太容易掉坑里了。
    qq191513
        22
    qq191513  
       2018-08-13 22:43:59 +08:00
    拿走不用谢我~
    def print_and_save_txt(str=None,filename=r'log.txt'):
    with open(filename, "a+") as log_writter:
    print(str)
    log_writter.write(str)
    oldbird
        23
    oldbird  
       2021-02-28 09:36:00 +08:00
    @gaayyy 请问最后如何做到实时写入文件和屏幕显示的?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5805 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 03:31 · PVG 11:31 · LAX 19:31 · JFK 22:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.