python - sys.settrace 似乎在线程中被忽略
问题描述
所以我开始研究一个实验性的调试器,试图解决我遇到的一些问题,因为我主要调试位于远程机器上的东西。
这是我拥有的代码示例:
debugger = threading.local()
debugger.instance = None
_logger = logging.getLogger(__name__)
class Debugger(object):
...
def __call__(self, frame, event, arg):
thread_name = threading.current_thread().getName()
_logger.debug(
"Start Trace (%s) %s %s",
thread_name,
event,
arg
)
...
def set_trace():
_logger.debug("[%s] Set trace", threading.current_thread().getName())
thread_name = threading.current_thread().getName()
try:
instance = debugger.instance
if not instance:
debugger.instance = Debugger()
instance = debugger.instance
except Exception:
debugger.instance = Debugger()
instance = debugger.instance
def destroy(instance):
def wrap():
_logger.debug("[%s] Destroying debugger instance", thread_name)
instance.stop()
return wrap
atexit.register(destroy(instance))
if not instance.stopped:
_logger.debug("[%s] Set trace to %s", thread_name, instance)
sys.settrace(instance)
else:
_logger.debug("[%s] Remove trace", thread_name)
sys.settrace(None)
以及程序的代码:
import sys
from threading import Thread
from threading import get_ident
import logging
logging.basicConfig(level='DEBUG')
value = 2
def start_job():
print("In thread", get_ident())
import d2
d2.set_trace()
# breakpoint()
print("In thread value", value)
print("End thread", get_ident())
thread = Thread(target=start_job, args=tuple())
thread.start()
这是我得到的日志:
....
In thread 139757304022784
DEBUG:d2:[Thread-1] Set trace
DEBUG:d2:[Thread-1] Waiting for the client from the async thread
DEBUG:d2:[Thread-1] Set trace to <d2.Debugger object at 0x7f1bc877fe80>
In thread value 2
End thread 139757304022784
....
此日志中的第一行来自 set_trace,第二行来自调试器的构造函数。第三行就在 sys.settrace 设置调试器之前。在线程中,值 2 是 set_trace 调用之后的行,最后一行几乎是线程本身的最后一行。
问题是,对于 MainThread,它可以完美运行,我实际上可以看到如下日志:
DEBUG:d2:Start Trace (MainThread) call None
DEBUG:d2:Start Trace (MainThread) line None
DEBUG:d2:Start Trace (MainThread) line None
DEBUG:d2:Start Trace (MainThread) call None
DEBUG:d2:Start Trace (MainThread) line None
但是对 settrace 的调用似乎完全被忽略了。我也尝试使用threading.settrace
它似乎或多或少地工作。它将开始调试线程,但实际上我不想跟踪整个线程,而只想跟踪我放置断点的地方。
最终,我希望能够sys.settrace(None)
禁用跟踪并在需要时让断点启用调试器。
编辑:我想我在这个问题中找到了这种行为的原因。“sys.settrace”是否在 Python 3.5 中正常工作,但在 Python 3.6 中不能正常工作?
每当输入新的本地范围时,都会调用跟踪函数(事件设置为“调用”);它应该返回对要用于新范围的本地跟踪函数的引用,如果不应该跟踪范围,则返回 None 。
显然,它不会在 settrace 之后立即开始跟踪,而是在调用 settrace() 后创建新的本地作用域之后才开始跟踪。
解决方案
推荐阅读
- csv - AWS Glue 爬虫无法提取 CSV 标头
- css - 需要图像反弹
- node.js - Sails.js 无法运行脚本:sails run rebuild-cloud-sdk
- c# - 从 FileSystemWatcher 事件调用的方法在更改富文本框文本后停止
- html - 关于通过 winhttp 安全网站进行身份验证的问题
- javascript - 使用 useState Hook 在功能组件中将 Render 道具与 Children 反应
- angular - 更新后如何使用管道编写 rxjs 捕获和映射函数
- r - 拆分一列,获取拆分列的平均值,并更新结果
- kubernetes - 来自 Kubernetes API 服务器 /healthz 的 401
- php - 当我尝试将我的网站上传到主机时出现错误