繁体   English   中英

如何跟踪现有python扭曲应用程序的执行情况

[英]How to trace execution of an existing python twisted application

所以...可能你们很多人会从你的职业生涯中认识到这一点。

你已经继承了数百个文件的代码库,数千行每个都有对象,闭包和全局变量的混合,没有单元测试,而且很多它实际上可能是死代码,永远不再被调用。 一个人(他是一个超级聪明的家伙,但是一个完整的黑客)写了大部分内容(就像所有的一样)并且他已经不在了。 有趣的python怪癖比比皆是,它做了所需的事情,但没有评论来表明他们为什么在那里。

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),并且有大量端点占用各种根。 每个都做“有趣”的事情,但基本上它们都与各种数据库或第三方休息端点进行通信,然后聚合某些格式的东西并返回休息响应。 扭曲是一个非常好的框架!

现在,有什么方法可以让扭曲的框架帮我开始调试吗? 像设置一些标志一样简单,以便每当触发回调时 - 它将打印传递给回调的方法和参数? 这不是我在文档中找到的东西。

你们做什么的? 任何提示和答案都会受到欢迎。

如果我有的话,我不会在我的本地开发盒上扭曲猴子。

更新 - 一些hacky进展............自己没有超过一些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')

但是,如果任何人有更好的东西-我很想知道!

一些工作已经开始使用Deferred工具,特别是更容易调试。 https://twistedmatrix.com/trac/ticket/1402上有一些信息,以及https://twistedmatrix.com/trac/ticket/4304引用的分支中的一些代码。 这些工具实际上并不是Twisted的一部分,所以尝试使用它们有点不方便。 在最坏的情况下,也许他们会给你一些想法,也许你真的会找到一种方法在你的应用程序上使用它们。

与您已编写的基于跟踪钩子的跟踪器类似,有twisted.python.util.spewerepsilon.spewer.Spewer 但是,这些可能实际上不会提供比您已经构建的工具更多的信息。

作为原始帖子添加此内容已经足够长了。 除了Jean-Paul所说的那篇文章之外 - 我在tap.py中编写了一个启动应用程序的黑客。 我会在这里发布,以防将来对任何人都有用。 它确实为我提供了我需要的信息 - 当我点击一个端点时会发生什么......显然,将这​​个与原始延迟链相关联的事情会更加令人敬畏。 我从Jean-Paul发布的链接中获取了一些代码 - 谢谢。

trace_exclusions = [
    "twisted",
    "DQL2SQL",
    "DDBClient",
    "exon_parser",
    "ontology",
    "pglib",
    "servers/interfaces/counter.py",
    "event_feed/feed_register.py",
    "database_notification_manager",
    "revenue_optimization"
    ]

def extractArgs(frame):
    co = frame.f_code
    dict = frame.f_locals
    n = co.co_argcount
    if co.co_flags & 4: n = n+1
    if co.co_flags & 8: n = n+1
    result = {}
    for i in range(n):
        name = co.co_varnames[i]
        if name != "self":
            r = dict.get(name, "----")
            r = str(r)
            if len(r) > 30:
                r = r[0:28] + '..'
            result[name] = r 
    return result

def tracefunc(frame, event, arg, indent=[0]):
    if frame.f_code.co_filename.startswith("/home/developer/projects/befogg/servers/nlp/src/"):
        if not any(te in frame.f_code.co_filename for te in trace_exclusions):
            if event == "call":
                indent[0] += 1
                print "-" * indent[0], frame.f_code.co_filename.replace("/home/developer/projects/befogg/servers/nlp/src/", ""), frame.f_code.co_name, "VARS:", frame.f_code.co_varnames
                print "-" * indent[0], frame.f_code.co_filename.replace("/home/developer/projects/befogg/servers/nlp/src/", ""), frame.f_code.co_name, "ARGS:", extractArgs(frame)
            if event == "return":
                indent[0] -= 1
    return tracefunc

import sys
sys.settrace(tracefunc)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM