后端开发中有时会遇到这种情况:进程运行中偶现,重启进程问题就消失;或者是,进程一定要运行一段时间才会出现问题;又或是,极难复现的问题出现了,然而已有的log不足以定位

对于这些情况,尽管大部分时候,我们可以通过在可能的地方加log,然后重启进程等待问题复现,但这样相对被动。我们都知道如果要调试C/C++程序,gdb attach上进程就可以,而python虽然有相似的工具pdb,但它无法附加到一个进程上,必须要用pdb启动进程,在实际环境中显然不管用,那么python是否有类似的办法来改变运行中进程的代码呢?这样我们就可以通过实时加log来定位问题,这样几乎可以解决python层面的任何问题

可以参考两篇文章:

简单来说,可以直接用gdb使用类似调试c程序的方式,但要求python进程是使用python-debug这种版本的python,同样不够实用。这里介绍博客中提到的“纯gdb”的方式,通过github上一个开源python包pyrasite,本质上是通过gdb的-eval-command和它的PyRun_SimpleString来向进程注入代码。

这个库有一些附加功能,可以通过它的文档去了解。这里只说实现进程注入的核心,是其中一个很短的文件injector.py,这里去掉了原文件中用于windows平台的一段代码,我们这里只考虑linux,核心代码如下:

import os

import subprocess

import platform

def inject(pid, filename, verbose=False, gdb_prefix=''):

"""Executes a file in a running Python process."""

filename = os.path.abspath(filename)

gdb_cmds = [

'PyGILState_Ensure()',

'PyRun_SimpleString("'

'import sys; sys.path.insert(0, \\"%s\\"); '

'sys.path.insert(0, \\"%s\\"); '

'exec(open(\\"%s\\").read())")' %

(os.path.dirname(filename),

os.path.abspath(os.path.join(os.path.dirname(__file__), '..')),

filename),

'PyGILState_Release($1)',

]

p = subprocess.Popen('%sgdb -p %d -batch %s' % (gdb_prefix, pid,

' '.join(["-eval-command='call %s'" % cmd for cmd in gdb_cmds])),

shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

out, err = p.communicate()

if verbose:

print(out)

print(err)

这个函数做的事很简单,不难看懂,所以,我们需要做的就是调用这个函数,传入pid和文件名,文件是一个你要对这个进程执行的python代码。现在我们运行一个很简单的python进程test.py:

import time

def b():

print('b')

while 1:

b()

time.sleep(1)

然后创建一个文件patch.py:

print('injecting')

def newb():

print('new b')

b = newb

在injector.py的末尾加上一段,以便接收命令行调用:

import sys

pid = sys.argv[1]

filename = sys.argv[2]

inject(int(pid), filename)

通过ps aux|grep test.py查看上面进程的pid,然后执行python injector.py pid patch.py,为方便反复测试可以这样:

pid=`ps aux | grep test.py | grep -v grep | awk '{print $2}'`;python injector.py $pid patch.py;echo $pid injected

输出如下:

至此就实现了进程注入。

注意点:

修改类或类方法和函数同理,改变类的方法时,直接使用类名classA.method = new_method会将变化应用到所有实例,注意对类方法来说在patch.py中定义时也要加上self参数

在patch.py中,我们可以直接对b赋值,因为我们gdb进入一个进程后,所在的上下文环境就是该进程的入口模块,可以通过打印globals()来看到有哪些全局变量,这些就是可以直接访问的对象。如果是在一个普通的业务进程中,必然有大量import,这种情况下你需要import相应模块再对该模块的函数或类进行修改,如import x.y.z as z; z.b = newb

特别需要注意的是,如果一个模块A使用了from B import func,那么如果你想改变A中运行的func,需要import A; A.func = newfunc,像这样改变B是没有用的:import B; B.func = newfunc,因为from .. import ..会将对象复制一份到本地命名空间。反之,如果A是使用import B并通过B.func进行调用,那么就应当import B进行修改

如果一个函数内部有阻塞式的while True,那么改变这个函数是没有用的,显然要应用改变的对象需要对象下一次被调用,这个不难理解但是容易漏想到

python多进程调试_使用pyrasite进行python进程调试,改变运行中进程的代码相关推荐

  1. python适用场景_你真的了解Python吗?什么场景使用多线程,什么场景使用多进程?...

    引言 涉及并发的场景,大家想到使用多线程或多进程解决并发问题; 一般情况下,解决多并发场景问题,多数语言采用多线程编程模式(线程是轻量级的进程,共用一份进程空间). 也同样适用于Python多并发处理 ...

  2. python编程基础_月隐学python第2课

    python编程基础_月隐学python第2课 学习目标 掌握变量的输入和输出 掌握数据类型的基本概念 掌握算数运算 1.变量的输入和输出 1.1 变量输入 使用input输入 input用于输入数据 ...

  3. 查看Python的版本_查看当前安装Python的版本

    一.查看Python的版本_查看当前安装Python的版本 具体方法: 首先按[win+r]组合键打开运行: 然后输入cmd,点击[确定]: 最后执行[python --version]命令即可. 特 ...

  4. python多进程优化_『Python』多进程处理

    尝试学习python的多进程模组,对比多线程,大概的区别在: 1.多进程的处理速度更快 2.多进程的各个子进程之间交换数据很不方便 多进程调用方式 进程基本使用multicore() 进程池优化进程的 ...

  5. python多进程优化_如何利用多进程优化Python视频应用

    如果要用Python播放视频,或者打开摄像头获取视频流,我们可以用OpenCV Python.但是在视频帧获取的时候同时做一些图像识别和处理,可能会因为耗时多而导致卡顿.一般来说,我们首先会想到把这些 ...

  6. 怎么让python一直执行_怎么才能让Python多进程不间断执行任务

    任务列表储存在mongoDB中 大概三百万条 每个任务执行结束会标记上 现在有个问题 每次脚本开始时读取100任务 用python多进程执行任务时 必须等待所有进程执行结束才能重新读取下一个100条 ...

  7. python pdb调试_使用Pdb进行Python调试

    python pdb调试 Debugging applications can sometimes be an unwelcome activity. You're busy working unde ...

  8. python多进程 保活_老板,你这个爬虫保活吗?

    点击上方"咸鱼学Python",选择"加为星标" 第一时间关注Python技术干货! 作者:wsgao 原文:https://wsgzao.github.io/ ...

  9. python多进程编程_【玩树莓】编程篇(八)Python多线程、多进程编程

    1.多任务编程 除了计算性能和图形显示以外,树莓派区别于Arduino的一大特点就是运行多任务操作系统.通过多任务系统用户可以同时执行多个互相独立的程序(任务),来完成不同的操作. 利用Python的 ...

最新文章

  1. 基于重力补偿的 PD 控制
  2. STM32的GPIO为输出模式时获取其输出状态
  3. SPI模式下MCU对SD卡的控制及操作命令
  4. gradle 插件 自定义_Gradle自定义插件
  5. java 网络编程connection timed out是什么意思_什么?听说这四个概念,很多 Java 老手都说不清...
  6. SQL Server元数据损坏(metadata corruption)修复
  7. 比较有意思的老家见闻一二三
  8. mysql删除端口配置文件_完美解决phpstudy安装后mysql无法启动(无需删除原数据库,无需更改任何配置,无需更改端口)直接共存...
  9. 第10题 正则表达式匹配(动态规划)
  10. Java虚拟机类加载机制浅谈
  11. 看淘宝“舞象”,微商式微
  12. 小技巧 - LeetCode 如何查看他人耗时更优的代码答案?
  13. 基于华为云IoT设计的智能门锁
  14. LAMP架构部署论坛
  15. Openxml 笔记
  16. 服务器配置参数主要有哪些
  17. cygwin linux 教程,Cygwin工具使用入门教程
  18. RuntimeError: Expected object of type torch.cuda.LongTensor but found type torch.cuda.IntTensor
  19. RK3399 GMAC驱动失败,打印如下log,DMA engine initialization failed 原因
  20. python编程视频剪辑_专治爱剪辑的片头片尾的脚本(Python)

热门文章

  1. python自动化办公都能做什么-用 Python 自动化办公,我与大神之间的差距一下就...
  2. python和java哪个好-Python和Java对比,全面解读哪个语言最赚钱,前景最好?
  3. python爬虫实例100例-python 爬虫实例
  4. python是什么编程语言-Python是什么?可能是最受欢迎的编程语言
  5. python开发软件的实例-由Python编写的MySQL管理工具代码实例
  6. python可以自学编程吗-编程学习第一步,让你20天搞定Python编程
  7. python爬虫菜鸟教程-Python爬虫学习100练001
  8. 横向对比5大开源语音识别工具包,CMU Sphinx最佳
  9. |ViaVoice(IBM语音识别输入系统)下载v9.1官方版 - 欧普软件下载
  10. JavaScript -- DOM树