Python:将所有函数包装在一个库中
我们使用另一个内部团队提供的库。 (摇摇欲坠的类比现在开始)
from externalTeam import dataCreator
datacreator.createPizza()
datacreator.createBurger()
datacreator.createHotDog()
最近我们发现他们的一个方法在某些情况下执行需要一分钟多的时间。为了调试这个问题,我必须进入我们的代码并在每次调用此方法时添加超时。
import time
from externalTeam import dataCreator
start = time.clock()
datacreator.createPizza()
stop = time.clock()
print "It took %s seconds to perform createPizza" % (str(stop-start))
事后看来,这是因为我们到处调用 createPizza,而我们不控制 createPizza 本身(这里的类比开始有点不成立)。我宁愿只在一个地方调用 createPizza ,并能够在其周围添加一个计时器。我的第一个想法是在我自己的包装类中创建一个包装所有方法的方法。但这与 DRY 相反,每当他们添加另一个方法时,我都必须更新我们的库来包装它:
import time
from externalTeam import dataCreator
def createPizza(self):
start = time.clock()
datacreator.createPizza()
stop = time.clock()
print "It took %s seconds to perform createPizza" % (str(stop-start))
def createBurger(self):
start = time.clock()
datacreator.createPizza()
stop = time.clock()
print "It took %s seconds to perform createBurger" % (str(stop-start))
def createHotDog(self):
start = time.clock()
datacreator.createPizza()
stop = time.clock()
print "It took %s seconds to perform createHotDog" % (str(stop-start))
我想要的是一种始终在从 dataCreator 调用的每个函数周围执行几行代码的方法。必须有某种方法可以通过中间类来做到这一点,该中间类的方法可以动态定义 - 或者更确切地说未定义,对吗?
We use a library provided by another internal team. (Shaky analogy starts now)
from externalTeam import dataCreator
datacreator.createPizza()
datacreator.createBurger()
datacreator.createHotDog()
Recently we found a single method of theirs was taking over a minute to execute in certain situations. To debug this, I had to go into our code and add timeouts around every call of this method.
import time
from externalTeam import dataCreator
start = time.clock()
datacreator.createPizza()
stop = time.clock()
print "It took %s seconds to perform createPizza" % (str(stop-start))
In hindsight, that's because we're calling createPizza all over the place, and we don't control createPizza itself (the analogy is starting to break down a little here). I'd rather just call createPizza in one place, and be able to add a timer around that. My first thought to accomplish this would be to create a wrap all their methods in my own wrapper class. That's the opposite of DRY though, and anytime they add another method I'd have to update our library to wrap that as well:
import time
from externalTeam import dataCreator
def createPizza(self):
start = time.clock()
datacreator.createPizza()
stop = time.clock()
print "It took %s seconds to perform createPizza" % (str(stop-start))
def createBurger(self):
start = time.clock()
datacreator.createPizza()
stop = time.clock()
print "It took %s seconds to perform createBurger" % (str(stop-start))
def createHotDog(self):
start = time.clock()
datacreator.createPizza()
stop = time.clock()
print "It took %s seconds to perform createHotDog" % (str(stop-start))
What I want is a way to always execute a few lines of code around every function that's being called from dataCreator. There must be some way to do that through an intermediate class whose methods can be dynamically defined - or rather left undefined, right?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我将创建一个
dataCreator
适配器类,其工作方式如下:methods2wrap
列表,其中包含来自dataCreator
的方法,这些方法需要包装到调试/计时功能。dataCreator
方法,将methods2wrap
中的方法包装到定时调试消息中。概念验证代码(该示例包装类
list
并在其方法append
周围插入调试时间戳)。当然,您可以在此示例的基础上进行构建并使其参数化,以便在初始化时您可以设置要包装的类以及应计时的方法...
编辑:请注意,每次都会重新分配
TO_OVERRIDE
__getattribute__
调用。这是设计使然。如果您将其作为类属性,__getattribute__
将递归循环(您应该使用对父__getattribute__
方法的显式调用来检索它,但这可能是比简单地从头开始重建列表要慢。
I would create a
dataCreator
adapter class that would work like this:methods2wrap
list of the methods fromdataCreator
that needs to be wrapped into the debugging/timing functionality.__getattribute__()
that would map 1:1 onto thedataCreator
methods, wrapping the methods inmethods2wrap
into a timing debug message.Proof-of-concept code (the example wrap the class
list
and insert a debugging timestamp around its methodappend
).Of course you could build on this example and make it parametric, so that at initialisation time you can set what class to wrap and what methods should be timed...
EDIT: Note that
TO_OVERRIDE
is reassigned at each__getattribute__
call. This is by design. If you you would make it as a class attribute,__getattribute__
would recursively loop (you should use an explicit call to the parent__getattribute__
method to retrieve it, but this would probably be slower than simply rebuild the list from scratch.HTH
如果您尝试分析 Python 代码,则应该使用 Python 的内置 分析库 而不是尝试手动完成。
If you're trying to profile Python code, you should use Python's built-in profiling libraries instead of trying to do it manually.
为什么不使用一个只调用其参数的包装函数呢?
并调用它:
请注意,您传递了函数本身,但没有调用它。
Why not a single wrapper function which just calls its argument?
and call it:
note you pass the function itself, but without calling it.
以下模板可能会有所帮助:
The following template could help: