自带的 print 函数居然会报错?(下)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 最近用 Python 写了几个简单的脚本来处理一些数据,因为只是简单功能所以我就直接使用 print 来打印日志。

解决办法


既然知道了问题原因,那解决起来就比较简单了,主要有以下几个方案:


  1. 使用 read() 函数读取管道中的数据,全部读取之后再关闭。


  1. 如果不需要子进程中的输出时,也可以将 command 的标准输出重定向到 /dev/null


  1. 也可以使用 Python3subprocess.Popen 模块来运行。


这里使用第一种方案进行演示:


import os
import time
if __name__ == '__main__':
    start = int(time.time())
    cmd = 'python test.py'
    with os.popen(cmd) as p:
        print p.read()
    end = int(time.time())
    print 'end****{}s'.format(end-start)


网络异常,图片无法展示
|


运行 task.py 之后不会再抛异常,同时也将 command 的输出打印出来。


线上修复时我没有采用这个方案,为了方便查看日志,还是使用标准的日志框架将日志输出到了 es 中,方便统一在 kibana 中进行查看。


由于日志框架并没有使用到管道,所以自然也不会有这个问题。


更多内容


问题虽然是解决了,其中还是涉及到了一些咱们平时不太注意的知识点,这次我们就来一起回顾一下。


首先是父子进程的内容,这个在 c/c++/python 中比较常见,在 Java/golang 中直接使用多线程、协程会更多一些。


比如这次提到的 Python 中的 os.popen() 就是创建了一个子进程,既然是子进程那肯定是需要和父进程进行通信才能达到协同工作的目的。


很容易想到,父子进程之间可以通过上文提到的管道(匿名管道)来进行通信。


还是以刚才的 Python 程序为例,当运行 task.py 后会生成两个进程:


网络异常,图片无法展示
|


分别进入这两个程序的 /proc/pid/fd 目录可以看到这两个进程所打开的文件描述符。


父进程:


网络异常,图片无法展示
|


子进程:


网络异常,图片无法展示
|


可以看到子进程的标准输出与父进程关联,也就是 popen() 所返回的那个文件描述符。


这里的 0 1 2 分别对应一个进程的stdin(标准输入)/stdout(标准输出)/stderr(标准错误)。


还有一点需要注意的是,当我们在父进程中打开的文件描述符,子进程也会继承过去;

比如在 task.py 中新增一段代码:


x = open("1.txt", "w")


之后查看文件描述符时会发现父子进程都会有这个文件:


网络异常,图片无法展示
|


但相反的,子进程中打开的文件父进程是不会有的,这个应该很容易理解。


总结


一些基础知识在排查一些诡异问题时显得尤为重要,比如本次涉及到的父子进程的管道通信,最后来总结一下:


  1. os.popen() 函数是异步执行的,如果需要拿到子进程的输出,需要自行调用 read() 函数。


  1. 父子进程是通过匿名管道进行通信的,当读取端关闭时,写入端输出到达管道最大缓存时会收到 SIGPIPE 信号,从而抛出 Broken pipe 异常。


  1. 子进程会继承父进程的文件描述符。


相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
算法 Unix 编译器
C语言表驱动法编程实践(精华帖,建议收藏并实践)
C语言表驱动法编程实践(精华帖,建议收藏并实践)
314 0
|
2月前
|
SQL 数据管理 BI
数据库操作三基石:DDL、DML、DQL 技术入门指南
本文围绕数据库操作核心语言 DDL、DML、DQL 展开入门讲解。DDL 作为 “结构建筑师”,通过CREATE(建库 / 表)、ALTER(修改表)、DROP(删除)等命令定义数据库结构;DML 作为 “数据管理员”,以INSERT(插入)、UPDATE(更新)、DELETE(删除)操作数据表记录,需搭配WHERE条件避免误操作;DQL 作为 “数据检索师”,通过SELECT结合WHERE、ORDER BY、LIMIT等子句实现数据查询与统计。三者相辅相成,是数据库操作的基础,使用时需注意 DDL 的不可撤销性、DML 的条件约束及 DQL 的效率优化,为数据库学习与实践奠定基础。
|
12月前
|
人工智能 安全 大数据
最新!阿里云入选福布斯·出海全球化品牌Top30
最新!阿里云入选福布斯·出海全球化品牌Top30
350 8
|
Java Linux Android开发
深入理解Android开发:从基础到高级
【9月更文挑战第17天】本文将深入探讨Android开发的各个方面,包括应用开发、操作系统等。我们将通过代码示例来展示如何创建一个简单的Android应用,并解释其背后的原理。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和启示。
|
消息中间件 负载均衡 Kafka
kafka rebalance你真的了解吗
今天主要分享一下 kafka 的 rebalance,在 kafka 中,rebalance 是一个十分重要的概念,很多时候引发的一些问题可能都是由于 rebalance 引起的,rebalance 也就是再均衡,顾名思义,再均衡就是再次负载均衡,下面会对再均衡进行一个详细的描述。
709 3
|
存储 网络协议 网络架构
|
存储 程序员 编译器
【C++ 模板类与虚函数】解析C++中的多态与泛型
【C++ 模板类与虚函数】解析C++中的多态与泛型
357 0
|
机器学习/深度学习 人工智能 TensorFlow
ModelScope使用之模型部署
ModelScope是阿里巴巴打造下一代开源的模型即服务共享平台,为泛AI开发者提供灵活、易用、低成本的一站式模型服务产品,让模型应用更简单!本文演示如何将模型部署到阿里云的EAS,对外提供服务。
16707 0
ModelScope使用之模型部署
《QT从基础到进阶·三十四》qobject_cast动态强制转换
《QT从基础到进阶·三十四》qobject_cast动态强制转换
1156 0