[英]Python: Print a variable's name and value?
在調試的時候,我們經常會看到這樣的打印語句:
print x # easy to type, but no context
print 'x=',x # more context, harder to type
12
x= 12
如何編寫一個 function 來獲取變量或變量名稱並打印其名稱和值? 我只對調試 output 感興趣,這不會合並到生產代碼中。
debugPrint(x) # or
debugPrint('x')
x=12
Python 3.8 f-string =
語法
它已經到了!
#!/usr/bin/env python3
foo = 1
bar = 2
print(f"{foo=} {bar=}")
輸出:
foo=1 bar=2
在提交https://github.com/python/cpython/commit/9a4135e939bc223f592045a38e0f927ba170da32 中添加“使用‘=’添加 f 字符串調試。” 哪些文件:
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``.
所以它也適用於任意表達式。 好的!
你可以只使用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
例如使用 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:
檢查當前幀()
CPython 實現細節:此函數依賴於解釋器中的 Python 堆棧幀支持,不能保證在 Python 的所有實現中都存在。 如果在沒有 Python 堆棧框架支持的實現中運行,則此函數返回 None。
我寫了以下內容以便能夠輸入類似的內容(在文件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)]
就是這樣:
# Print the line and filename, function call, the class, str representation and some other info
# Inspired by https://stackoverflow.com/a/8856387/5353461
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
對於那些還沒有使用 python 3.8 的人,這里有一個替代方案。
這是此處找到的一個已關閉的 2009 年重復問題的已接受答案的修改后的較短版本(在 15 年 8 月 14 日下面也被錯誤復制,錯誤是 re 包含硬編碼的函數名稱“varname” ' 而不是顯示的函數名稱 'getm')。 原文在這里: How can you print a variable name in python? ?
為了解釋下面的 re,inspect.getframeinfo(inspect.currentframe(), f_back)[3] 給出了列表中的函數簽名
[' p(prev)\n']
強制轉換為 str 使您不必循環遍歷一個項目的列表。 re 尋找一個 '(' 必須被轉義,下一個 '(' 是在匹配中創建一個組來引用,然后 [^)] 表示任何不是 ')' 的字符,'^' 表示'不是' 在這種情況下,方括號 [] 表示匹配其中的任何字符,后面的 '*' 是 0 次或多次的量詞。 然后用 ')' 關閉組,匹配關閉的 ')' 並瞧:
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,2017 年 12 月 18 日,21:07:28)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] 在達爾文
剛剛開發了@Padraic Cunningham 的答案,以采用任意數量的變量。 我喜歡這種方法,因為它的工作原理就像print(x1, x2, x3)
- 不需要在''
包裝 var 名稱。
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
我在 jupyterlab 中這樣做是為了像變量打印一樣獲得 matlab:
def debug(var):
stack = traceback.extract_stack()
filename, lineno, function_name, name = stack[-2]
print(name[6:-1] , ':' , var)
用法:
x=1
debug(x)
產量:
x : 1
實際上,為了輸入 output 格式的方便和簡潔,我使用的確切代碼是:
import traceback
def p(var):
stack = traceback.extract_stack()
filename, lineno, function_name, name = stack[-2]
print( "{:<25}".format(name[2:-1]) , ': ' , var)
相當丑陋,但工作:
import inspect, re
def getm(p):
for line in inspect.getframeinfo(inspect.currentframe().f_back)[3]:
match = re.search(r'\bvarname\s*\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*\)', line)
if match:
return match.group(1)
x=21
search = getm(x);
print (search , '=' , eval(search))
一個簡單的例子是:
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))
希望能幫助到你!
我剛剛編造了一個像這樣打印任意表達式的函數:
import inspect, pprint
def pp(n):
print()
print(n,"=")
f=inspect.stack()[1].frame
pprint.pprint(eval(n,f.f_globals,f.f_locals))
(我在名稱之前使用了一個空行,在值 'cuz 之前使用了一個換行符,因為在我的情況下,我需要打印大型數據結構。使用換行符更容易閱讀這樣的輸出。)
只要您不傳遞不受信任的輸入,它就是安全的。
您可能也對我的dump
模塊感興趣。 它以人類可讀的形式打印所有對象的字段。 證明對調試非常有用。
多個變量(將@Blender 響應更進一步):
def debug(variables, sep =''):
vars = variables.split(',')
for var in vars:
print(var, '=', repr(eval(var)), end = sep)
例子:
import bumpy as np
gPrimeLinear = lambda z: np.ones(np.array(z).size)*z
gPrimeSigmoid = lambda z: 1./(1+np.exp(-z))*(1-1./(1+np.exp(-z)))
gPrimeTanh = lambda z: 1- np.tanh(z)**2
z = np.array([ 0.2, 0.4, 0.1])
debug("z, gPrimeLinear(z), gPrimeSigmoid(z), gPrimeTanh(z)", '\n')
這將返回:
> z = array([0.2, 0.4, 0.1])
> gPrimeLinear(z) = array([0.2, 0.4, 0.1])
> gPrimeSigmoid(z) = array([0.24751657, 0.24026075, 0.24937604])
> gPrimeTanh(z) = array([0.96104298, 0.85563879, 0.99006629])
當從變量的值中找到變量的名稱時,
您可能有多個變量等於相同的值,
例如 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']]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.