Python中重定向控制台输出到文件后发送邮件遇文件截断问题求助
解决控制台输出文件截断的问题
看起来你遇到的问题主要来自两个方面:原程序的输出缓冲没有真正写入磁盘,以及读取文件时的指针位置错误。咱们一步步来解决:
1. 先解决原程序的输出缓冲问题
当你用python my_app.py > console.txt重定向输出时,Python的stdout默认是块缓冲(只有当缓冲区满了或者程序退出时才会写入磁盘),而不是行缓冲(终端环境下才默认行缓冲)。这就导致即使你在读取时做了flush和fsync,原程序的输出可能还留在缓冲区里没写到磁盘。
你可以用以下方法强制原程序实时输出:
- 运行时添加
-u参数:直接用python -u my_app.py > console.txt启动程序,-u参数会让stdout和stderr变成无缓冲(或行缓冲),输出会立即写入磁盘。 - 修改
my_app.py内部刷新缓冲:在原程序中,每次输出后手动调用sys.stdout.flush();或者在程序开头设置sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', buffering=1)(Python3,行缓冲),确保输出实时写入。 - 用
stdbuf命令强制Shell行缓冲:如果不能修改原程序或Python参数,可通过Shell工具强制缓冲模式:stdbuf -oL python my_app.py > console.txt,-oL表示将stdout设为行缓冲。
2. 修正读取文件时的指针错误
看你的代码,打开文件后先执行了print(attachment.readline(-20)),这会把文件指针移动到该行的末尾,之后再调用attachment.read()只能读取指针之后的内容,前面的部分就被漏掉了,这也是附件内容截断的一个关键原因。
修正方法:
- 如果只是测试读取,可以删掉那行测试代码;
- 如果需要保留测试,在读取完整内容前把指针移回文件开头:
with open(filename, "r") as attachment: # 测试读取 print(attachment.readline(-20)) # 移回文件开头 attachment.seek(0) # 读取完整内容 part.set_payload(attachment.read())
另外,读取文件时不需要r+模式(读写模式),用只读r模式就足够了,避免不必要的权限问题;而且buffering=1在只读模式下意义不大,直接默认即可。
3. 确保读取前彻底刷新原程序的输出
如果你是在同一个脚本里既运行my_app.py又读取文件,那要确保原程序的子进程已经完成输出并刷新。比如用subprocess模块调用原程序,等待子进程结束后再读取文件:
import subprocess subprocess.run(["python", "-u", "my_app.py"], stdout=open("console.txt", "w")) # 此时子进程已结束,文件内容完整 with open("console.txt", "r") as f: full_content = f.read()
这样组合下来,应该就能拿到完整的console.txt内容作为邮件附件了。
内容的提问来源于stack exchange,提问作者Dmitri K.
相关产品推荐
相关产品推荐

