是否有内置函数来打印对象的所有当前属性和值?

时间:2008-10-10 16:19:28

标签: python debugging introspection pretty-print python-datamodel

所以我在这里寻找的是PHP的print_r功能。这样我就可以通过查看相关对象的状态来调试我的脚本。

25 个答案:

答案 0 :(得分:858)

您希望vars()pprint()混合:

from pprint import pprint
pprint(vars(your_object))

答案 1 :(得分:488)

你真的把两件事混在一起。

使用dir()vars()inspect模块获取您感兴趣的内容(我以__builtins__为例;您可以使用任何对象)。

>>> l = dir(__builtins__)
>>> d = __builtins__.__dict__

打印那本词典然而你喜欢这样:

>>> print l
['ArithmeticError', 'AssertionError', 'AttributeError',...

>>> 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',
...

交互式调试器中还可以使用漂亮打印作为命令:

(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__'}

答案 2 :(得分:169)

def dump(obj):
  for attr in dir(obj):
    print("obj.%s = %r" % (attr, getattr(obj, attr)))

有很多第三方功能可以根据作者的喜好添加异常处理,国家/特殊字符打印,嵌套对象等递归等功能。但他们基本上都归结为此。

答案 3 :(得分:47)

已经提到了

dir ,但这只会给你属性的名字。如果你想要他们的价值观,请尝试__dict __。

class O:
   def __init__ (self):
      self.value = 3

o = O()

这是输出:

>>> o.__dict__

{'value': 3}

答案 4 :(得分:20)

要打印对象的当前状态,您可以:

>>> obj # in an interpreter

print repr(obj) # in a script

print obj

为您的课程定义__str____repr__方法。来自Python documentation

  

__repr__(self)repr()内置函数和字符串调用   转换(反向引号)到   计算“官方”字符串   对象的表示。如果有的话   可能,这应该看起来像一个   有效的Python表达式   用来重新创建一个对象   相同的价值(给定一个适当的   环境)。如果这不可能,   形式为“&lt; ...一些有用的字符串   说明...&gt;“应该退回。   返回值必须是字符串   宾语。如果一个类定义 repr ()   但不是__str__(),那么__repr__()是   也用于“非正式”字符串   表示实例   上课是必需的。这通常是   用于调试,所以很重要   表示是   信息丰富,毫不含糊。

     

__str__(self)str()内置函数和打印调用   计算“非正式”的陈述   对象的字符串表示。   这与__repr__()不同   它不一定是有效的Python   表达:更方便或   可以使用简洁的表示   代替。返回值必须是a   字符串对象。

答案 5 :(得分:19)

您可以使用“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']
>>>

另一个有用的功能是帮助。

>>> 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

答案 6 :(得分:15)

可能值得一试 -

Is there a Python equivalent to Perl's Data::Dumper?

我的建议是这个 -

https://gist.github.com/1071857

请注意,perl有一个名为Data :: Dumper的模块,它将对象数据转换回perl源代码(注意:它不会将代码转换回源代码,而且几乎总是你不希望代码方法函数在输出)。这可以用于持久性,但通常用于调试。

标准的python pprint有很多东西无法实现,特别是当它看到一个对象的实例并且给你对象的内部十六进制指针时它会停止下降(错误,指针不是很多)顺便使用)。简而言之,python就是关于这个面向对象的伟大范例,但是开箱即用的工具是为了处理除了对象以外的东西而设计的。

perl Data :: Dumper允许您控制您想要的深度,并且还可以检测循环链接结构(这非常重要)。这个过程在perl中基本上更容易实现,因为对象除了祝福之外没有特别的魔力(一个普遍定义良好的过程)。

答案 7 :(得分:11)

在大多数情况下,使用__dict__dir()可以获得您想要的信息。如果您碰巧需要更多细节,标准库包含inspect模块,可以让您获得一些令人印象深刻的细节。一些真正的信息提示包括:

  • 功能和方法参数的名称
  • 类层次结构
  • 函数/类对象实现的源代码
  • 框架对象中的局部变量

如果您只是在寻找“我的对象具有哪些属性值?”,那么dir()__dict__可能就足够了。如果你真的想深入了解任意对象的当前状态(请记住,在python中几乎所有东西都是对象),那么inspect值得考虑。

答案 8 :(得分:7)

元编程示例Dump object with magic

$ 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

没有参数:

$ python dump.py
<__main__.Data instance at 0x00A052D8>

使用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>

它有点过时但仍在工作。

答案 9 :(得分:4)

我建议使用help(your_object)

help(dir)

 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)

Without arguments, equivalent to locals().
With an argument, equivalent to object.__dict__.

答案 10 :(得分:4)

以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)

答案 11 :(得分:4)

如果您正在使用它进行调试,并且您只想要递归转储所有内容,则接受的答案是不满意的,因为它要求您的类已经具有良好的__str__实现。如果情况并非如此,那么效果会更好:

import json
print(json.dumps(YOUR_OBJECT, 
                 default=lambda obj: vars(obj),
                 indent=1))

答案 12 :(得分:3)

转储&#34; myObject&#34;:

from bson import json_util
import json

print(json.dumps(myObject, default=json_util.default, sort_keys=True, indent=4, separators=(',', ': ')))

我尝试过vars()和dir();两者都因我想要的而失败了。 vars()没有工作,因为该对象没有__dict __(exceptions.TypeError:vars()参数必须具有__dict__属性)。 dir()并不是我想要的:它只是一个字段名称列表,没有给出值或对象结构。

我认为json.dumps()适用于大多数没有default = json_util.default的对象,但是我在对象中有一个datetime字段,因此标准的json序列化器失败了。见How to overcome "datetime.datetime not JSON serializable" in python?

答案 13 :(得分:3)

尝试ppretty

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)

输出:

__main__.A(_p = 8, foo = [0, 1, ..., 8, 9], s = 5)

答案 14 :(得分:3)

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))

答案 15 :(得分:3)

我需要在某些日志中打印DEBUG信息,并且无法使用pprint,因为它会破坏它。相反,我做了这件事并得到了几乎相同的东西。

DO = DemoObject()

itemDir = DO.__dict__

for i in itemDir:
    print '{0}  :  {1}'.format(i, itemDir[i])

答案 16 :(得分:2)

为什么不简单:

for key,value in obj.__dict__.iteritems():
    print key,value

答案 17 :(得分:2)

试试beeprint

它不仅可以帮助你打印对象变量,还可以帮助你输出漂亮的输出,如下所示:

class(NormalClassNewStyle):
  dicts: {
  },
  lists: [],
  static_props: 1,
  tupl: (1, 2)

答案 18 :(得分:2)

我赞成只提到pprint的答案。需要说明的是,如果要在复杂的数据结构中查看所有,请执行以下操作:

from pprint import pprint
pprint(my_var)

my_var 是您感兴趣的变量。当我使用pprint(vars(my_var))时,我什么也没得到,这里的其他答案没有帮助,或者方法看起来不必要很长。顺便说一下,在我的特定情况下,我正在检查的代码有一本字典词典。

值得指出的是,对于某些自定义类,您最终可能会得到一种无用的<someobject.ExampleClass object at 0x7f739267f400>类型的输出。在这种情况下,您可能必须实现__str__方法,或尝试其他一些解决方案。我仍然希望找到适用于所有场景的简单方法,而不需要第三方库。

答案 19 :(得分:2)

pprint包含一个“漂亮的打印机”,用于生成美观的数据结构表示。格式化程序生成数据结构的表示,可以由解释器正确解析,并且人类也可以轻松阅读。如果可能,输出将保留在一行中,并在分割为多行时缩进。

答案 20 :(得分:1)

对于每个与之抗争的人

  • vars()没有返回所有属性。
  • dir()没有返回属性&#39;值。

以下代码打印obj的{​​strong>所有属性及其值:

for attr in dir(obj):
        try:
            print("obj.{} = {}".format(attr, getattr(obj, attr)))
        except AttributeError:
            print("obj.{} = ?".format(attr))

答案 21 :(得分:0)

您可以尝试使用Flask调试工具栏 https://pypi.python.org/pypi/Flask-DebugToolbar

from flask import Flask
from flask_debugtoolbar import DebugToolbarExtension

app = Flask(__name__)

# the toolbar is only enabled in debug mode:
app.debug = True

# set a 'SECRET_KEY' to enable the Flask session cookies
app.config['SECRET_KEY'] = '<replace with a secret key>'

toolbar = DebugToolbarExtension(app)

答案 22 :(得分:0)

我喜欢使用python对象内置类型keysvalues

对于属性,无论它们是方法还是变量:

o.keys()

对于这些属性的值:

o.values()

答案 23 :(得分:0)

  

是否有内置功能可以打印对象的所有当前属性和值?

不。最受欢迎的答案不包括某些类型的属性,被接受的答案显示了如何获取所有属性,包括非公共api的方法和部分。但是,没有完善的 builtin 函数。

因此,简短的推论是您可以编写自己的脚本,但是它将计算属性和其他计算的数据描述符(它们是公共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))

其他答案有问题

在具有许多不同类型的数据成员的类上观察当前投票最高的答案的应用:

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))

仅打印:

{'baz': 'baz'}

由于vars 返回对象的__dict__,并且它不是副本,因此,如果您修改vars返回的字典,则还要修改__dict__对象本身。

vars(obj)['quux'] = 'WHAT?!'
vars(obj)

返回:

{'baz': 'baz', 'quux': 'WHAT?!'}

-这很糟糕,因为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']

我们可以看到,dir仅返回 all (实际上只是大多数)与对象关联的名称。

注释中提到的

inspect.getmembers同样存在缺陷-它返回所有名称​​和值。

来自班级

在教学中,我让我的学生创建一个函数,该函数提供对象的语义公共API:

def api(obj):
    return [name for name in dir(obj) if name[0] != '_']

我们可以扩展它以提供对象语义名称空间的副本,但是我们需要排除未分配的__slots__,如果我们正在接受请求对于严重的“当前属性”,我们需要排除计算出的属性(因为它们可能会变得昂贵,并且可能被解释为不是“当前”):

from types import FunctionType
from inspect import getmembers

def attrs(obj):
     disallowed_properties = {
       name for name, value in getmembers(type(obj)) 
         if isinstance(value, (property, FunctionType))}
     return {
       name: getattr(obj, name) for name in api(obj) 
         if name not in disallowed_properties and hasattr(obj, name)}

现在我们不计算或显示属性quux:

>>> attrs(obj)
{'bar': 0, 'baz': 'baz', 'foo': ''}

注意事项

但是也许我们确实知道我们的财产并不昂贵。我们可能想要更改逻辑以使其也包括在内。也许我们想排除 other custom 数据描述符。

然后,我们需要进一步自定义此功能。因此,我们不能拥有一个神奇地确切知道我们想要并提供它的内置函数是有道理的。这是我们需要创建自己的功能。

结论

没有内置函数可以执行此操作,因此您应该执行最适合自己情况的语义。

答案 24 :(得分:0)

无论您是在__init__还是外部的类中定义变量,该方法都有效。

your_obj = YourObj()
attrs_with_value = {attr: getattr(your_obj, attr) for attr in dir(your_obj)}