【发布时间】:2014-07-08 17:16:00
【问题描述】:
所以……你们中的许多人可能会从你的职业生涯中认识到这一点。
您继承了包含数百个文件、数千行的代码库,每个文件都混合了对象、闭包和全局变量,没有进行单元测试,而且其中很多实际上可能是不再被调用的死代码。一个人(他是一个超级聪明的人,但也是一个彻头彻尾的黑客)写了大部分(就像所有这些),但他已经不在了。有趣的 python 怪癖比比皆是,它们做了想要的事情,但没有 cmets 来表明它们为什么存在。
d = dict(d)
其中 d 已经是字典(传递到方法中),是我个人迄今为止最喜欢的...(出于某种原因,浅拷贝 - 我花了一些时间来解决这个问题)不同路径使用的通用方法系统并知道他们需要做什么
if <passed_in_param>["XXX"] = <something>:
<pathA>
return A
elif <passed_in_param>["ZZZ"] = <somethingElse>:
<pathB>
return B
这是……呃……等等等等等等 - 只是那些渴望被重构的常见东西。
我真正的问题是,我需要先了解应用程序的工作原理,然后才能真正开始调试它......再次 - 我敢肯定,这对许多人来说是熟悉的领域。
系统使用twisted来托管一堆http端点(使用twistd),并且有很多端点占据了不同的根。每个都做“有趣”的事情,但基本上它们都与各种数据库或第三方休息端点通信,然后聚合一些东西格式化一些东西并返回一个休息响应。 Twisted 是一个非常好的框架!
现在,有什么方法可以让扭曲的框架帮助我开始调试它?像设置一些标志这样简单的事情,以便每当触发回调时 - 它会打印传递给回调的方法和参数?这不是我能够在文档中找到的内容。
你们是做什么的?欢迎提供任何提示和答案。
如果我也有的话,我不会在我的本地开发盒上扭曲猴子补丁。
更新 - 一些骇人听闻的进展............ 我自己并没有超越一些 hackyness,我想出了一些比没有好一点的东西。
在 tap.py 文件中,twistd 启动器启动我已经把这个(以防其他人觉得这很有用):
trace_exclusions = ["twisted", "DQL2SQL", "DDBClient", "exon_parser", "ontology", "pglib"]
def tracefunc(frame, event, arg, indent=[0]):
if frame.f_code.co_filename.startswith("<!redacted!>/src/"):
if not any(te in frame.f_code.co_filename for te in trace_exclusions):
if event == "call":
indent[0] += 2
print "-" * indent[0], frame.f_code.co_filename.replace("/<!redacted!>/src/", ""), frame.f_code.co_name, frame.f_code.co_varnames
if event == "return":
indent[0] -= 2
return tracefunc
import sys
sys.settrace(tracefunc)
我得到了一些有用的输出:
-- servers/http/base.py getResourceFor ('self', 'request', 'path', 'full_path', 'channel', 'category', 'service', 'version', 'market', 'locale', 'currency', 'query_id', 'extra_id')
-- servers/carhire_api/carhire_api.py render_GET ('self', 'request', 'entity_id', 'distance', 'dql', 'd', 'response')
---- servers/carhire_api/carhire_api.py get_int_parameter ('request', 'param_key')
---- servers/carhire_api/carhire_api.py get_int_parameter ('request', 'param_key')
---- beautify/deferred_entity_beautify.py get_entity_id ('pkid', 'val', 'iface', 'd')
------ cache/apc_cache.py __getitem__ ('self', 'key')
------ beautify/deferred_entity_beautify.py get_interface_id ()
------ kraken/client.py get ('self', 'key', 'd')
-------- kraken/client.py _get_multi ('self', 'connection', 'keys', 'task', 'd')
---------- kraken/twist.py get ('self', 'namespace', 'keys', 'task', 'the_size', 'req', 'r', 'the_timeout', 'l', 'idx', 'tmp_keys', 'd_l', 'exc')
------------ kraken/__init__.py get ('self', 'namespace', 'keys', 'req')
-------------- kraken/__init__.py request ('self', 'method', 'namespace', 'data', 'req')
---------------- kraken/__init__.py <genexpr> ('.0', 'x')
---------------- kraken/__init__.py <genexpr> ('.0', 'x')
但如果有人有更好的 - 我希望知道!
【问题讨论】:
-
哦 - 我忘了提。我已经尝试使用带有打印方法名称的东西的 sys.settrace() 函数。显然,扭曲的反应堆会发送 lot 或消息。我可能会设置一个排除集或其他东西,但如果 twisted 有一个不错的调试选项,我很想知道它
-
您是否考虑在 Twisted 的代码库或您继承的代码库中的战略位置设置 PDB 断点?然后,您可以单步执行代码、检查堆栈、局部变量等。
-
是的 - 我让它在调试器中运行并使用断点。问题是因为我真的不知道断点在哪里,所以我有点卡住了。一旦您离开代码并最终进入反应器循环(在您注册了一些延迟之后),那么您可以在再次退出之前按下 [F6] 可能 forever。
-
我明白了。但是,如果不知道您究竟想了解有关该应用程序的什么,很难给出具体的建议。但我发现检查调用堆栈(PDB 中的
w)和上下移动堆栈帧(u和d)在这种情况下通常会有所帮助。 -
是的,真正的问题是,通过延迟,您正在注册未来,然后,在某个时刻(信息已进入套接字)您的代码将触发。当那个东西触发时,你不再有它在代码中被声明为未来的上下文......所以我可以断点一个看起来很有趣的方法,我什至可以在调用堆栈中暂停,但我无法找到这段逻辑在哪里注册发生。调用堆栈最终进入扭曲并结束......
标签: python debugging refactoring twisted