python python等价于'#define func()'或如何在python中注释掉函数调用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2006190/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
python equivalent of '#define func() ' or how to comment out a function call in python
提问by random guy
my python code is interlaced with lots of function calls used for (debugging|profiling|tracing etc.) for example:
我的python代码与许多用于(调试|分析|跟踪等)的函数调用交织在一起,例如:
import logging
logging.root.setLevel(logging.DEBUG)
logging.debug('hello')
j = 0
for i in range(10):
j += i
logging.debug('i %d j %d' % (i,j))
print(j)
logging.debug('bye')
i want to #define these resource consuming functions out of the code. something like the c equivalent
我想从代码中#define 这些资源消耗函数。类似于 c 的等价物
#define logging.debug(val)
yes, i know the logging module logging level mechanism can be used to mask out loggings below set log level. but, im asking for a general way to have the python interpreter skip functions (that take time to run even if they dont do much)
是的,我知道日志记录模块日志记录级别机制可用于屏蔽低于设置日志级别的日志记录。但是,我要求有一种通用的方法来让 python 解释器跳过函数(即使它们没有做太多也需要时间来运行)
one idea is to redefine the functions i want to comment out into empty functions:
一个想法是将我想注释掉的函数重新定义为空函数:
def lazy(*args): pass
logging.debug = lazy
the above idea still calls a function, and may create a myriad of other problems
上面的想法仍然调用一个函数,并且可能会产生无数其他问题
回答by Dave Kirby
Python does not have a preprocessor, although you could run your python source through an external preprocessor to get the same effect - e.g. sed "/logging.debug/d"
will strip out all the debug logging commands. This is not very elegant though - you will end up needing some sort of build system to run all your modules through the preprocessor and perhaps create a new directory tree of the processed .py files before running the main script.
Python 没有预处理器,尽管您可以通过外部预处理器运行您的 Python 源代码以获得相同的效果 - 例如sed "/logging.debug/d"
将删除所有调试日志命令。虽然这不是很优雅 - 您最终将需要某种构建系统来通过预处理器运行所有模块,并且可能在运行主脚本之前创建一个处理过的 .py 文件的新目录树。
Alternatively if you put all your debug statements in an if __debug__:
block they will get optimised out when python is run with the -O (optimise) flag.
或者,如果您将所有调试语句放在一个if __debug__:
块中,当使用 -O(优化)标志运行 python 时,它们将得到优化。
As an aside, I checked the code with the dis module to ensure that it did get optimised away. I discovered that both
顺便说一句,我用 dis 模块检查了代码,以确保它确实得到了优化。我发现两者
if __debug__: doStuff()
and
和
if 0: doStuff()
are optimised, but
已优化,但
if False: doStuff()
is not. This is because False is a regular Python object, and you can in fact do this:
不是。这是因为 False 是一个常规的 Python 对象,你实际上可以这样做:
>>> False = True
>>> if False: print "Illogical, captain"
Illogical, captain
Which seems to me a flaw in the language - hopefully it is fixed in Python 3.
这在我看来是语言中的一个缺陷——希望它在 Python 3 中得到修复。
Edit:
编辑:
This is fixed in Python 3: Assigning to True or False now gives a SyntaxError.
Since True and False are constants in Python 3, it means that if False: doStuff()
is now optimised:
这在 Python 3 中已修复:分配给 True 或 False现在会给出 SyntaxError。由于 True 和 False 是 Python 3 中的常量,这意味着if False: doStuff()
现在进行了优化:
>>> def f():
... if False: print( "illogical")
...
>>> dis.dis(f)
2 0 LOAD_CONST 0 (None)
3 RETURN_VALUE
回答by Peter Hansen
Although I think the question is perfectly clear and valid (notwithstanding the many responses that suggest otherwise), the short answer is "there's no support in Python for this".
虽然我认为这个问题非常清楚和有效(尽管有许多回应暗示其他问题),但简短的回答是“Python 不支持这个”。
The only potential solution other than the preprocessor suggestionwould be to use some bytecode hacking. I won't even begin to imagine how this should work in terms of the high-level API, but at a low level you could imagine examining code objects for particular sequences of instructions and re-writing them to eliminate them.
除了预处理器建议之外,唯一可能的解决方案是使用一些字节码黑客。我什至不会开始想象就高级 API 而言这应该如何工作,但在低级,您可以想象检查特定指令序列的代码对象并重新编写它们以消除它们。
For example, look at the following two functions:
例如,看下面两个函数:
>>> def func():
... if debug: # analogous to if __debug__:
... foo
>>> dis.dis(func)
2 0 LOAD_GLOBAL 0 (debug)
3 JUMP_IF_FALSE 8 (to 14)
6 POP_TOP
3 7 LOAD_GLOBAL 1 (foo)
10 POP_TOP
11 JUMP_FORWARD 1 (to 15)
>> 14 POP_TOP
>> 15 LOAD_CONST 0 (None)
18 RETURN_VALUE
Here you could scan for the LOAD_GLOBAL
of debug
, and eliminate it and everything up to the JUMP_IF_FALSE
target.
在这里,您可以扫描LOAD_GLOBAL
of debug
,并消除它以及JUMP_IF_FALSE
目标的所有内容。
This one is the more traditional C-style debug() function that gets nicely obliterated by a preprocessor:
这是更传统的 C 风格的 debug() 函数,它被预处理器很好地消除了:
>>> def func2():
... debug('bar', baz)
>>> dis.dis(func2)
2 0 LOAD_GLOBAL 0 (debug)
3 LOAD_CONST 1 ('bar')
6 LOAD_GLOBAL 1 (baz)
9 CALL_FUNCTION 2
12 POP_TOP
13 LOAD_CONST 0 (None)
16 RETURN_VALUE
Here you would look for LOAD_GLOBAL
of debug
and wipe everything up to the corresponding CALL_FUNCTION
.
在这里,您将查找LOAD_GLOBAL
ofdebug
并将所有内容擦除到相应的CALL_FUNCTION
.
Of course, both of those descriptions of what you would do are far simpler than what you'd really need for all but the most simplistic patterns of use, but I think it would be feasible. Would make a cute project, if nobody's already done it.
当然,除了最简单的使用模式之外,这两种对您将要做什么的描述都比您真正需要的要简单得多,但我认为这是可行的。会做一个可爱的项目,如果没有人已经这样做了。
回答by Tomas Brambora
Well, you can always implement your own simple preprocessor that does the trick. Or, even better, you can use an already existing one. Say http://code.google.com/p/preprocess/
好吧,您始终可以实现自己的简单预处理器来实现这一目标。或者,更好的是,您可以使用现有的。说http://code.google.com/p/preprocess/
回答by Andrew Aylett
Before you do this, have you profiled to verify that the logging is actually taking a substantial amount of time? You may find that you spend more time trying to remove the calls than you save.
在您执行此操作之前,您是否进行了分析以验证日志记录实际上花费了大量时间?您可能会发现尝试删除呼叫所花费的时间多于节省的时间。
Next, have you tried something like Psyco? If you've got things set up so logging is disabled, then Psyco may be able to optimise away most of the overhead of calling the logging function, noticing that it will always return without action.
接下来,你有没有尝试过像Psyco这样的东西?如果您已经设置好日志被禁用,那么 Psyco 可能能够优化掉调用日志函数的大部分开销,注意到它总是会在没有操作的情况下返回。
If you still find logging taking an appreciable amount of time, you might then want to look at overriding the logging function inside critical loops, possibly by binding a local variable to either the logging function or a dummy function as appropriate (or by checking for None before calling it).
如果您仍然发现日志记录花费了相当长的时间,那么您可能想要查看在关键循环内覆盖日志记录函数,可能通过将局部变量绑定到日志记录函数或适当的虚拟函数(或通过检查 None在调用它之前)。
回答by richo
define a function that does nothing, ie
定义一个什么都不做的函数,即
def nuzzing(*args, **kwargs): pass
Then just overload all the functions you want to get rid of with your function, ala
然后用你的函数重载你想摆脱的所有函数,ala
logging.debug = nuzzing
回答by David Underhill
I like the 'if __debug_' solution except that putting it in front of every call is a bit distracting and ugly. I had this same problem and overcame it by writing a script which automatically parses your source files and replaces logging statements with pass statements (and commented out copies of the logging statements). It can also undo this conversion.
我喜欢 'if __debug_' 解决方案,只是把它放在每次调用的前面有点让人分心和难看。我遇到了同样的问题,并通过编写一个脚本来克服它,该脚本自动解析您的源文件并用 pass 语句替换日志语句(并注释掉日志语句的副本)。它还可以撤消此转换。
I use it when I deploy new code to a production environment when there are lots of logging statements which I don't need in a production setting and they are affecting performance.
当我将新代码部署到生产环境时,我会使用它,因为在生产环境中有很多我不需要的日志语句,并且它们会影响性能。
You can find the script here: http://dound.com/2010/02/python-logging-performance/
你可以在这里找到脚本:http: //dound.com/2010/02/python-logging-performance/
回答by jldupont
Use a module scoped variable?
使用模块范围的变量?
from config_module import debug_flag
from config_module import debug_flag
and use this "variable" to gate access to the logging function(s). You would build yourself a logging
module that uses the debug_flag
to gate the logging functionality.
并使用这个“变量”来控制对日志功能的访问。您将自己构建一个logging
模块,该模块使用debug_flag
来控制日志记录功能。
回答by Khelben
I think that completely aboiding the calling on a function is not posible, as Python works in a different way that C. The #define takes place in the pre-compiler, before the code is compiled. In Python, there's no such thing.
我认为完全避免调用函数是不可能的,因为 Python 的工作方式与 C 不同。 #define 在编译代码之前发生在预编译器中。在 Python 中,没有这样的东西。
If you want to completely remove the calling to debug in a work environment, I think the only way if to actually change the code before execution. With a script previous to execution you could comment/uncomment the debug lines.
如果你想在工作环境中完全删除调试的调用,我认为唯一的方法是在执行之前实际更改代码。使用执行前的脚本,您可以注释/取消注释调试行。
Something like this:
像这样的东西:
File logging.py
文件记录.py
#Main module
def log():
print 'logging'
def main():
log()
print 'Hello'
log()
File call_log.py
文件 call_log.py
import re
#To log or not to log, that's the question
log = True
#Change the loging
with open('logging.py') as f:
new_data = []
for line in f:
if not log and re.match(r'\s*log.*', line):
#Comment
line = '#' + line
if log and re.match(r'#\s*log.*', line):
#Uncomment
line = line[1:]
new_data.append(line)
#Save file with adequate log level
with open('logging.py', 'w') as f:
f.write(''.join(new_data))
#Call the module
import logging
logging.main()
Of course, it has its problems, specially if there are a lot of modules and are complex, but could be usable if you need to absolutely avoid the calling to a function.
当然,它有它的问题,特别是如果模块很多并且很复杂,但是如果您需要绝对避免调用函数,则可以使用。
回答by user238424
You can't skipfunction calls. You could redefine these as empty though, e.g. by creating another logging object that provides the same interface, but with empty functions.
您不能跳过函数调用。您可以将它们重新定义为空,例如,通过创建另一个提供相同接口但具有空函数的日志对象。
But by far the cleanest approach is to ignore the low priority log messages (as you suggested):
但到目前为止,最干净的方法是忽略低优先级的日志消息(如您所建议的):
logging.root.setLevel(logging.CRITICAL)