print x # easy to type, but no context
print 'x=',x # more context, harder to type
12
x= 12
如何编写一个函数,该函数接受一个变量或变量名,并打印出其名称和值?我只对调试输出感兴趣,这不会被纳入生产代码中。
debugPrint(x) # or
debugPrint('x')
x=12
print x # easy to type, but no context
print 'x=',x # more context, harder to type
12
x= 12
debugPrint(x) # or
debugPrint('x')
x=12
Python 3.8 f-string =
syntax
终于来了!
#!/usr/bin/env python3
foo = 1
bar = 2
print(f"{foo=} {bar=}")
输出:
foo=1 bar=2
添加了提交https://github.com/python/cpython/commit/9a4135e939bc223f592045a38e0f927ba170da32,“使用'='添加 f-string 调试”记录的内容:
f-strings now support = for quick and easy debugging
-----------------------------------------------------
Add ``=`` specifier to f-strings. ``f'{expr=}'`` expands
to the text of the expression, an equal sign, then the repr of the
evaluated expression. So::
x = 3
print(f'{x*9 + 15=}')
Would print ``x*9 + 15=42``.
所以它也适用于任意表达式。太好了!
梦想:从变量名字中获取类似JavaScript的字典键
我发现Python在几乎每一个方面都比JavaScript更好,但我真的很喜欢这个JavaScript功能:
let abc = 1
let def = 2
console.log({abc, def})
在JavaScript中可以工作,因为{abc,def}
扩展为{abc:1,def:2}
。这太棒了,并且除了日志记录之外,在代码的其他地方经常使用。
目前在Python中除了使用locals
之外,无法很好地实现: Python variables as keys to dict
print(f'{foo=}')
比OP要求的some(foo)
或some('foo')
多出了很多标点符号。这看起来很傻,但重点是要有一个非常简单的东西,而且这个解决方案容易弄错标点符号,从我的角度来看影响效果。 - Stéphane Gourichonpylint(logging-fstring-interpolation)
。 - Wtowerdict
,所以通过调用它的__str__
,print(f'{kwargs=}')
会给出类似于kwargs={'a': 1, 'b': 2}
的输出。缺少什么? - Ciro Santilli OurBigBook.com您可以直接使用eval
:
def debug(variable):
print variable, '=', repr(eval(variable))
更一般地说(在调用函数的上下文中实际有效,并且不会在debug('variable')
上出现问题,但仅限于CPython):
from __future__ import print_function
import sys
def debug(expression):
frame = sys._getframe(1)
print(expression, '=', repr(eval(expression, frame.f_globals, frame.f_locals)))
而且你可以做:
>>> x = 1
>>> debug('x + 1')
x + 1 = 2
eval
的安全问题,我不认为这是个问题,因为这永远不会出现在生产代码中。 - Eli Rose例如,在Python3.8中使用最新的f'{var = }'
特性:
>>> a = 'hello'
>>> print(f'{a = }')
a = 'hello'
import inspect
import re
def debugPrint(x):
frame = inspect.currentframe().f_back
s = inspect.getframeinfo(frame).code_context[0]
r = re.search(r"\((.*)\)", s).group(1)
print("{} = {}".format(r,x))
这种方法并不适用于所有的Python版本:
inspect.currentframe()
CPython实现细节: 该函数依赖解释器中对Python栈帧的支持,但并不是所有Python实现都保证存在该支持。如果运行在没有Python栈帧支持的实现中,该函数将返回None。
print(x1, x2, x3)
一样-不需要用''
包装变量名。import inspect
import re
def prinfo(*args):
frame = inspect.currentframe().f_back
s = inspect.getframeinfo(frame).code_context[0]
r = re.search(r"\((.*)\)", s).group(1)
vnames = r.split(", ")
for i,(var,val) in enumerate(zip(vnames, args)):
print(f"{var} = {val}")
x1 = 1
x2 = 2
x3 = 3
prinfo(x1, x2, x3)
x1 = 1
x2 = 2
x3 = 3
describe.py
的第41行):describe('foo' + 'bar')
describe(numpy.zeros((2, 4)))
并查看:
describe.py@41 describe('foo' + 'bar') = str(foobar) [len=6]
describe.py@42 describe(numpy.zeros((2, 4))) = ndarray(array([[0., 0., 0., 0.],
[0., 0., 0., 0.]])) [shape=(2, 4)]
Here's how:
# Print the line and filename, function call, the class, str representation and some other info
# Inspired by https://dev59.com/rWox5IYBdhLWcg3w95A9#8856387
import inspect
import re
def describe(arg):
frame = inspect.currentframe()
callerframeinfo = inspect.getframeinfo(frame.f_back)
try:
context = inspect.getframeinfo(frame.f_back).code_context
caller_lines = ''.join([line.strip() for line in context])
m = re.search(r'describe\s*\((.+?)\)$', caller_lines)
if m:
caller_lines = m.group(1)
position = str(callerframeinfo.filename) + "@" + str(callerframeinfo.lineno)
# Add additional info such as array shape or string length
additional = ''
if hasattr(arg, "shape"):
additional += "[shape={}]".format(arg.shape)
elif hasattr(arg, "__len__"): # shape includes length information
additional += "[len={}]".format(len(arg))
# Use str() representation if it is printable
str_arg = str(arg)
str_arg = str_arg if str_arg.isprintable() else repr(arg)
print(position, "describe(" + caller_lines + ") = ", end='')
print(arg.__class__.__name__ + "(" + str_arg + ")", additional)
else:
print("Describe: couldn't find caller context")
finally:
del frame
del callerframeinfo
https://gist.github.com/HaleTom/125f0c0b0a1fb4fbf4311e6aa763844b
def debug(var):
stack = traceback.extract_stack()
filename, lineno, function_name, name = stack[-2]
print(name[6:-1] , ':' , var)
用法:
x=1
debug(x)
yields:
x : 1
实际上,我使用的准确代码是为了方便输入和输出格式的清晰度。如果您想以完全相同的方式使用它,请使用以下代码:
import traceback
def p(var):
stack = traceback.extract_stack()
filename, lineno, function_name, name = stack[-2]
print( "{:<25}".format(name[2:-1]) , ': ' , var)
对于那些尚未使用Python 3.8的人,这里提供一种替代方案。
这是一个修改后的、更短的答案,来自于2009年关闭的重复问题,该问题在下面的链接中找到(在2015年8月14日以下也出现了错误的复制,错误在于re包含硬编码的函数名'varname'而不是所示的函数名'getm')。原始链接在此处: 如何在Python中打印变量名??
为了解释下面的re,inspect.getframeinfo(inspect.currentframe(), f_back)[3]会返回一个列表,其中包含函数签名。
[' p(prev)\n']
def p(x):
import inspect
import re
m = re.search('\(([^)]*)\)',str(inspect.getframeinfo(inspect.currentframe().f_back)[3]))
print(f' {m.group(1)}: {x}')
这个能在2.7版本上工作吗?等我检查一下...看起来不行。我看到了一两个其他的变化,没有使用inspect.getframeinfo(inspect.currentframe().f_back)[3],所以也许其中一个会起作用。你需要检查重复项并仔细查看答案。 还要注意的是,有些答案说要注意可能与各种解决方案不兼容的python解释器。以上内容适用于
Python 3.6.4 (v3.6.4:d48ecebad5, Dec 18 2017, 21:07:28)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] 在 darwin 上
def debugPrint(*expr):
text = traceback.extract_stack()[-2][3]
begin = text.find('debugPrint(') + len('debugPrint(')
end = text.find(')',begin)
text=[name.strip() for name in text[begin:end].split(',')]
for t, e in text, expr:
print(str(t) + " = " + str(e))
希望能对你有所帮助!
当从变量的值中查找变量名时,
您可能有几个变量等于相同的值,
例如var1 = 'hello'和var2 = 'hello'。
我对您的问题的解决方案:
def find_var_name(val):
dict_list = []
global_dict = dict(globals())
for k, v in global_dict.items():
dict_list.append([k, v])
return [item for item in dict_list if item[1] == val]
var1 = 'hello'
var2 = 'hello'
find_var_name('hello')
输出
[['var1', 'hello'], ['var1', 'hello']]