fue*_*sjr 876 python debugging introspection pretty-print python-datamodel
所以我在这里寻找的是像PHP的print_r函数.这样我就可以通过查看相关对象的状态来调试我的脚本.
Jer*_*ell 924
你想vars()混合pprint():
from pprint import pprint
pprint(vars(your_object))
Run Code Online (Sandbox Code Playgroud)
小智 536
你真的把两件事混在了一起.
使用dir(),vars()或inspect模块来得到你所感兴趣的东西(我用__builtins__作为一个例子,你可以使用任何对象,而不是).
>>> l = dir(__builtins__)
>>> d = __builtins__.__dict__
Run Code Online (Sandbox Code Playgroud)
打印那本字典然而你喜欢:
>>> print l
['ArithmeticError', 'AssertionError', 'AttributeError',...
Run Code Online (Sandbox Code Playgroud)
要么
>>> from pprint import pprint
>>> pprint(l)
['ArithmeticError',
'AssertionError',
'AttributeError',
'BaseException',
'DeprecationWarning',
...
>>> pprint(d, indent=2)
{ 'ArithmeticError': <type 'exceptions.ArithmeticError'>,
'AssertionError': <type 'exceptions.AssertionError'>,
'AttributeError': <type 'exceptions.AttributeError'>,
...
'_': [ 'ArithmeticError',
'AssertionError',
'AttributeError',
'BaseException',
'DeprecationWarning',
...
Run Code Online (Sandbox Code Playgroud)
交互式调试器中还可以使用漂亮的打印作为命令:
(Pdb) pp vars()
{'__builtins__': {'ArithmeticError': <type 'exceptions.ArithmeticError'>,
'AssertionError': <type 'exceptions.AssertionError'>,
'AttributeError': <type 'exceptions.AttributeError'>,
'BaseException': <type 'exceptions.BaseException'>,
'BufferError': <type 'exceptions.BufferError'>,
...
'zip': <built-in function zip>},
'__file__': 'pass.py',
'__name__': '__main__'}
Run Code Online (Sandbox Code Playgroud)
Dan*_*ski 192
def dump(obj):
for attr in dir(obj):
print("obj.%s = %r" % (attr, getattr(obj, attr)))
Run Code Online (Sandbox Code Playgroud)
有很多第三方功能可以根据作者的喜好添加异常处理,国家/特殊字符打印,嵌套对象递归等功能.但他们都基本归结为此.
edu*_*ffy 53
dir已被提及,但这只会给你属性的名字.如果你想要他们的价值观,请尝试__dict__.
class O:
def __init__ (self):
self.value = 3
o = O()
Run Code Online (Sandbox Code Playgroud)
这是输出:
>>> o.__dict__
{'value': 3}
Run Code Online (Sandbox Code Playgroud)
Aar*_*all 35
是否有内置函数来打印对象的所有当前属性和值?
不。最高票的答案排除了某些类型的属性,接受的答案显示了如何获取所有属性,包括方法和非公共 api 的部分。但是没有很好的完整的内置函数。
所以简短的推论是您可以编写自己的,但它会计算属性和其他计算出的数据描述符,这些数据描述符是公共 API 的一部分,您可能不希望这样:
from pprint import pprint
from inspect import getmembers
from types import FunctionType
def attributes(obj):
disallowed_names = {
name for name, value in getmembers(type(obj))
if isinstance(value, FunctionType)}
return {
name: getattr(obj, name) for name in dir(obj)
if name[0] != '_' and name not in disallowed_names and hasattr(obj, name)}
def print_attributes(obj):
pprint(attributes(obj))
Run Code Online (Sandbox Code Playgroud)
观察当前投票最多的答案在具有许多不同类型数据成员的类上的应用:
from pprint import pprint
class Obj:
__slots__ = 'foo', 'bar', '__dict__'
def __init__(self, baz):
self.foo = ''
self.bar = 0
self.baz = baz
@property
def quux(self):
return self.foo * self.bar
obj = Obj('baz')
pprint(vars(obj))
Run Code Online (Sandbox Code Playgroud)
只打印:
{'baz': 'baz'}
Run Code Online (Sandbox Code Playgroud)
因为vars 只返回__dict__对象的 ,而不是副本,所以如果你修改 vars 返回的 dict,你也修改__dict__了对象本身的 。
vars(obj)['quux'] = 'WHAT?!'
vars(obj)
Run Code Online (Sandbox Code Playgroud)
返回:
{'baz': 'baz', 'quux': 'WHAT?!'}
Run Code Online (Sandbox Code Playgroud)
-- 这很糟糕,因为 quux 是一个我们不应该设置的属性,也不应该在命名空间中......
在当前接受的答案(和其他答案)中应用建议也好不到哪里去:
>>> dir(obj)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'bar', 'baz', 'foo', 'quux']
Run Code Online (Sandbox Code Playgroud)
正如我们所见,dir只返回与对象关联的所有(实际上只是大部分)名称。
inspect.getmembers,在评论中提到,同样有缺陷 - 它返回所有名称和值。
在教学时,我让我的学生创建一个函数,该函数提供对象的语义公共 API:
>>> dir(obj)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'bar', 'baz', 'foo', 'quux']
Run Code Online (Sandbox Code Playgroud)
我们可以扩展它以提供对象语义命名空间的副本,但我们需要排除__slots__未分配的,如果我们认真对待“当前属性”的请求,我们需要排除计算属性(如它们可能会变得昂贵,并且可能被解释为不是“当前的”):
def api(obj):
return [name for name in dir(obj) if name[0] != '_']
Run Code Online (Sandbox Code Playgroud)
现在我们不计算或显示属性 quux:
>>> attrs(obj)
{'bar': 0, 'baz': 'baz', 'foo': ''}
Run Code Online (Sandbox Code Playgroud)
但也许我们确实知道我们的房产并不昂贵。我们可能想要改变逻辑以包含它们。也许我们想排除其他 自定义数据描述符。
然后我们需要进一步定制这个功能。因此,我们不能拥有一个神奇地知道我们想要什么并提供它的内置函数是有道理的。这是我们需要自己创建的功能。
没有内置函数可以执行此操作,您应该根据您的情况执行语义上最合适的操作。
Joe*_*ora 23
您可以使用"dir()"函数执行此操作.
>>> import sys
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__', '__stdin__', '__stdo
t__', '_current_frames', '_getframe', 'api_version', 'argv', 'builtin_module_names', 'byteorder
, 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle', 'exc_clear', 'exc_info'
'exc_type', 'excepthook', 'exec_prefix', 'executable', 'exit', 'getcheckinterval', 'getdefault
ncoding', 'getfilesystemencoding', 'getrecursionlimit', 'getrefcount', 'getwindowsversion', 'he
version', 'maxint', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_
ache', 'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setprofile', 'setrecursionlimit
, 'settrace', 'stderr', 'stdin', 'stdout', 'subversion', 'version', 'version_info', 'warnoption
', 'winver']
>>>
Run Code Online (Sandbox Code Playgroud)
另一个有用的功能是帮助.
>>> help(sys)
Help on built-in module sys:
NAME
sys
FILE
(built-in)
MODULE DOCS
http://www.python.org/doc/current/lib/module-sys.html
DESCRIPTION
This module provides access to some objects used or maintained by the
interpreter and to functions that interact strongly with the interpreter.
Dynamic objects:
argv -- command line arguments; argv[0] is the script pathname if known
Run Code Online (Sandbox Code Playgroud)
jfs*_*jfs 20
要打印对象的当前状态,您可以:
>>> obj # in an interpreter
Run Code Online (Sandbox Code Playgroud)
要么
print repr(obj) # in a script
Run Code Online (Sandbox Code Playgroud)
要么
print obj
Run Code Online (Sandbox Code Playgroud)
对于您的类定义__str__或__repr__方法.从Python文档:
__repr__(self)由repr()内置函数和字符串转换(反向引号)调用,以计算对象的"官方"字符串表示形式.如果可能的话,这应该看起来像一个有效的Python表达式,可用于重新创建具有相同值的对象(给定适当的环境).如果这不可能,则应返回"<......一些有用的描述...>"形式的字符串.返回值必须是字符串对象.如果一个类定义了repr()但是没有__str__(),那么__repr__()当需要该类的实例的"非正式"字符串表示时,也会使用它.这通常用于调试,因此表示信息丰富且明确是很重要的.
__str__(self)由str()内置函数和print语句调用,以计算对象的"非正式"字符串表示形式.这不同之处__repr__()在于它不必是有效的Python表达式:可以使用更方便或简洁的表示.返回值必须是字符串对象.
小智 15
可能值得一试 -
是否有与Perl的Data :: Dumper等效的Python?
我的建议是这个 -
https://gist.github.com/1071857
请注意,perl有一个名为Data :: Dumper的模块,它将对象数据转换回perl源代码(注意:它不会将代码转换回源代码,而且几乎总是不希望输出中的对象方法函数).这可以用于持久性,但共同的目的是用于调试.
标准的python pprint有很多东西无法实现,特别是当它看到一个对象的实例并且给你对象的内部十六进制指针时,它会停止下降(错误,该指针不是很多用途)方式).简而言之,python就是关于这个面向对象的伟大范例,但是你开箱即用的工具是为了处理除了对象以外的东西而设计的.
perl Data :: Dumper允许您控制您想要的深度,并且还可以检测循环链接结构(这非常重要).这个过程在perl中基本上更容易实现,因为对象除了祝福之外没有特别的魔力(一个普遍定义良好的过程).
元编程示例使用魔法转储对象:
$ cat dump.py
#!/usr/bin/python
import sys
if len(sys.argv) > 2:
module, metaklass = sys.argv[1:3]
m = __import__(module, globals(), locals(), [metaklass])
__metaclass__ = getattr(m, metaklass)
class Data:
def __init__(self):
self.num = 38
self.lst = ['a','b','c']
self.str = 'spam'
dumps = lambda self: repr(self)
__str__ = lambda self: self.dumps()
data = Data()
print data
Run Code Online (Sandbox Code Playgroud)
没有参数:
$ python dump.py
<__main__.Data instance at 0x00A052D8>
Run Code Online (Sandbox Code Playgroud)
使用Gnosis Utils:
$ python dump.py gnosis.magic MetaXMLPickler
<?xml version="1.0"?>
<!DOCTYPE PyObject SYSTEM "PyObjects.dtd">
<PyObject module="__main__" class="Data" id="11038416">
<attr name="lst" type="list" id="11196136" >
<item type="string" value="a" />
<item type="string" value="b" />
<item type="string" value="c" />
</attr>
<attr name="num" type="numeric" value="38" />
<attr name="str" type="string" value="spam" />
</PyObject>
Run Code Online (Sandbox Code Playgroud)
它有点过时但仍在工作.
试试漂亮
from ppretty import ppretty
class A(object):
s = 5
def __init__(self):
self._p = 8
@property
def foo(self):
return range(10)
print ppretty(A(), show_protected=True, show_static=True, show_properties=True)
Run Code Online (Sandbox Code Playgroud)
输出:
__main__.A(_p = 8, foo = [0, 1, ..., 8, 9], s = 5)
Run Code Online (Sandbox Code Playgroud)
我建议使用help(your_object)。
help(dir)
Run Code Online (Sandbox Code Playgroud)If called without an argument, return the names in the current scope. Else, return an alphabetized list of names comprising (some of) the attributes of the given object, and of attributes reachable from it. If the object supplies a method named __dir__, it will be used; otherwise the default dir() logic is used and returns: for a module object: the module's attributes. for a class object: its attributes, and recursively the attributes of its bases. for any other object: its attributes, its class's attributes, and recursively the attributes of its class's base classes.
help(vars)
Run Code Online (Sandbox Code Playgroud)Without arguments, equivalent to locals(). With an argument, equivalent to object.__dict__.
小智 5
为什么不做一些简单的事情:
for key,value in obj.__dict__.iteritems():
print key,value
Run Code Online (Sandbox Code Playgroud)
小智 5
from pprint import pprint
def print_r(the_object):
print ("CLASS: ", the_object.__class__.__name__, " (BASE CLASS: ", the_object.__class__.__bases__,")")
pprint(vars(the_object))
Run Code Online (Sandbox Code Playgroud)
小智 5
如果您正在使用它进行调试,并且您只想要递归转储所有内容,那么接受的答案就不会令人满意,因为它要求您的类已经具有良好的__str__实现.如果情况并非如此,那么效果会更好:
import json
print(json.dumps(YOUR_OBJECT,
default=lambda obj: vars(obj),
indent=1))
Run Code Online (Sandbox Code Playgroud)
这将以json或yaml缩进格式递归打印所有对象内容:
import jsonpickle # pip install jsonpickle
import json
import yaml # pip install pyyaml
serialized = jsonpickle.encode(obj, max_depth=2) # max_depth is optional
print json.dumps(json.loads(serialized), indent=4)
print yaml.dump(yaml.load(serialized), indent=4)
Run Code Online (Sandbox Code Playgroud)
如果您想查看复杂数据结构中的所有值,请执行以下操作:
from pprint import pprint
pprint(my_var)
Run Code Online (Sandbox Code Playgroud)
其中my_var是您感兴趣的变量。当我使用时pprint(vars(my_var)),我什么也没得到,这里的其他答案没有帮助,或者该方法看起来不必要的长。顺便说一句,在我的特定情况下,我正在检查的代码有一个字典的字典。
值得指出的是,对于某些自定义类,您可能最终会得到无用的<someobject.ExampleClass object at 0x7f739267f400>输出。在这种情况下,您可能必须实现一种__str__方法,或尝试其他一些解决方案。
我还发现,在一个例子中,我得到了这种object类型的输出,vars()向我展示了我想要的东西。因此,涵盖这两种情况的更好解决方案是分别尝试这两种情况。但使用vars()有时会引发异常,例如,TypeError: vars() argument must have __dict__ attribute.
我仍然想找到一些简单的东西,可以在所有场景中使用,而不需要第三方库。
无论变量在类中、 __init__ 内部或外部如何定义,这都有效。
your_obj = YourObj()
attrs_with_value = {attr: getattr(your_obj, attr) for attr in dir(your_obj)}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
746140 次 |
| 最近记录: |