print()方法从字面上打印传递的表达式以及计算出的输出,以便快速调试

Sag*_*pta 26 python debugging logging

我希望能够使用print()或类似的方法执行python调试,在此方法中,除了通常的输出外,它还会打印传递的表达式。

例如,以下代码:

print(42 + 42)
print(type(list))
print(datetime.now())
Run Code Online (Sandbox Code Playgroud)

电流输出:

84
<class 'type'>
2019-08-15 22:43:57.805861
Run Code Online (Sandbox Code Playgroud)

预期产量:

42 + 42 : 84
type(list) : <class 'type'>
datetime.now() : 2019-08-15 22:43:57.805861
Run Code Online (Sandbox Code Playgroud)

当前,可以通过手动添加表达式字符串来实现相同目的(不是那么优雅,而且违反了DRY原理)。

print("42 + 42 : ", 42 + 42)
print("type(list) : ", type(list))
print("datetime.now() : ", datetime.now())
Run Code Online (Sandbox Code Playgroud)

我试图覆盖内置打印,但是没有成功:

import builtins
def print(*args, **kwargs):
    return builtins.print(*args, **kwargs)  # passed expression isn't available here as string!
Run Code Online (Sandbox Code Playgroud)

有没有办法做到这一点?谢谢!

sna*_*erb 19

f字符串将在Python 3.8(当前为beta)中支持类似的功能。

文档

f字符串(例如f'{expr =}')将扩展为表达式的文本,等号,然后扩展为所求值表达式的表示形式。例如:

>>> user = 'eric_idle'
>>> member_since = date(1975, 7, 31)
>>> f'{user=} {member_since=}'
"user='eric_idle' member_since=datetime.date(1975, 7, 31)"
Run Code Online (Sandbox Code Playgroud)

常用的f字符串格式说明符允许对表达式结果的显示方式进行更多控制:

>>> delta = date.today() - member_since
>>> f'{user=!s}  {delta.days=:,d}'
'user=eric_idle  delta.days=16,075'
Run Code Online (Sandbox Code Playgroud)

=说明符将显示整个表达式,以便可以显示计算结果:

>>> print(f'{theta=}  {cos(radians(theta))=:.3f}')
theta=30  cos(radians(theta))=0.866
Run Code Online (Sandbox Code Playgroud)


it'*_*het 11

通常,我认为如果您发现自己正在使用eval,可能有更好的方法来完成您要尝试的操作,但是:

for statement in ["42 + 42", "type(list)", "datetime.now()"]:
    print("{} : {}".format(statement, eval(statement))
Run Code Online (Sandbox Code Playgroud)


Hoo*_*oog 9

您可以定义一个superprint函数并打印出来然后计算一个字符串:

from datetime import datetime

def superprint(str):
    print(str," : ",eval(str))

a = "42 + 42"
b = "type(list)"
c = "datetime.now()"
superprint(a)
superprint(b)
superprint(c)
Run Code Online (Sandbox Code Playgroud)

输出值

42 + 42  :  84
type(list)  :  <class 'type'>
datetime.now()  :  2019-08-15 14:44:43.072780
Run Code Online (Sandbox Code Playgroud)

如果您可以忍受将要打印的所有内容都用引号引起来,这可能对您有用。


aug*_*men 8

您可以使用模块检查code_context从调用方获取源代码行():

from inspect import getframeinfo, currentframe


def vprint(value):
    caller = currentframe().f_back
    info = getframeinfo(caller)
    label = ''.join(info.code_context).strip()
    label = label.replace('vprint(', '')[:-1].strip()
    print(label, '=', value)


>>> vprint(12 + 3)
12 + 3 = 15
>>> vprint(type(list))
type(list) = <type 'type'>
>>> vprint(lambda x: x + 1)
lambda x: x + 1 = <function <lambda> at 0x7f93c104b9b0>
Run Code Online (Sandbox Code Playgroud)

仅适用于单行评估。由于code_context仅返回执行的行(而不是整个指令),因此可能会发生以下情况:

>>> vprint([''] +
...:     ['a', 'b'])
['a', 'b'] = ['', 'a', 'b']
>>> vprint(math.log(
...:   2 * math.pi))
2 * math.pi) = 1.83787706641
Run Code Online (Sandbox Code Playgroud)

注意:\对此进行了修正(缩进看起来仍然很奇怪):

>>> vprint(math.log( \
...:   2 * math.pi))
math.log(   2 * math.pi) = 1.83787706641
Run Code Online (Sandbox Code Playgroud)