1258

所以我在这里寻找的是 PHP 的print_r函数。

这样我就可以通过查看相关对象的状态来调试我的脚本。

4

29 回答 29

1176

你想vars()混合pprint()

from pprint import pprint
pprint(vars(your_object))
于 2008-10-11T01:16:32.493 回答
741

你真的把两种不同的东西混合在一起了。

使用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__'}
于 2008-10-10T17:27:06.077 回答
271
def dump(obj):
  for attr in dir(obj):
    print("obj.%s = %r" % (attr, getattr(obj, attr)))

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

于 2008-10-10T16:36:28.457 回答
83

dir已经提到过,但这只会给你属性的名称。如果您也想要它们的值,请尝试__dict__.

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

o = O()

这是输出:

>>> o.__dict__

{'value': 3}
于 2008-10-10T16:44:50.170 回答
49

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

否。最受好评的答案不包括某些类型的属性,并且接受的答案显示了如何获取所有属性,包括非公共 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))

其他答案的问题

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

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,你也在修改__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只返回与对象关联的所有(实际上只是大多数)名称。

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': ''}

注意事项

但也许我们确实知道我们的房产并不昂贵。我们可能想要更改逻辑以包含它们。也许我们想排除其他 自定义数据描述符。

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

结论

没有内置函数可以做到这一点,您应该做在语义上最适合您的情况的事情。

于 2019-12-01T18:26:56.773 回答
24

您可以使用“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
于 2008-10-10T16:20:40.547 回答
23

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

>>> obj # in an interpreter

或者

print repr(obj) # in a script

或者

print obj

为您的类定义__str____repr__方法。从Python 文档

__repr__(self)repr()内置函数和字符串转换(反引号)调用,以计算对象的“官方”字符串表示。如果可能的话,这应该看起来像一个有效的 Python 表达式,可用于重新创建具有相同值的对象(给定适当的环境)。如果这不可能,则应返回“<...一些有用的描述...>”形式的字符串。返回值必须是字符串对象。如果一个类定义了repr () 但未定义__str__(),则__repr__()当需要该类实例的“非正式”字符串表示时也使用 then。这通常用于调试,因此表示信息丰富且明确是很重要的。

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

于 2008-10-11T07:29:09.653 回答
18

可能值得一试——

是否有与 Perl 的 Data::Dumper 等效的 Python?

我的建议是——

https://gist.github.com/1071857

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

标准 python pprint 无法实现许多事情,特别是当它看到一个对象的实例并为您提供对象的内部十六进制指针时它只是停止下降(错误,该指针并没有被大量使用)道路)。所以简而言之,python 就是关于这个伟大的面向对象的范例,但是你开箱即用的工具是为处理对象以外的东西而设计的。

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

于 2012-11-15T04:11:48.243 回答
17

我建议使用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__.
于 2018-12-07T10:49:44.137 回答
13

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

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

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

于 2008-10-15T14:53:54.790 回答
11

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

import json
print(json.dumps(YOUR_OBJECT, 
                 default=lambda obj: vars(obj),
                 indent=1))
于 2014-11-23T21:20:22.207 回答
8

试试漂亮

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)
于 2016-07-28T07:14:28.417 回答
7

一个带有魔法的元编程示例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

没有参数:

$蟒蛇转储.py
<__main__.Data instance at 0x00A052D8>

使用Gnosis 实用程序

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

它有点过时但仍在工作。

于 2008-10-11T07:53:33.863 回答
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))
于 2014-07-14T15:01:07.297 回答
5

这会以 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)
于 2016-03-04T19:32:37.153 回答
4

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

from pprint import pprint
pprint(my_var)

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

值得指出的是,对于一些自定义类,您最终可能会得到一种无用<someobject.ExampleClass object at 0x7f739267f400>的输出。在这种情况下,您可能必须实现一种__str__方法,或尝试其他一些解决方案。

我还发现,在我得到这种object类型的输出的一个实例中,vars()向我展示了我想要的东西。因此,涵盖这两种情况的更好解决方案是分别尝试两种情况。但是 usingvars()有时会抛出异常,例如TypeError: vars() argument must have __dict__ attribute.

我仍然想找到适用于所有场景的简单工具,无需第三方库。

于 2017-09-28T04:35:31.753 回答
3

为什么不简单:

for key,value in obj.__dict__.iteritems():
    print key,value
于 2013-06-14T09:20:39.960 回答
3

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

DO = DemoObject()

itemDir = DO.__dict__

for i in itemDir:
    print '{0}  :  {1}'.format(i, itemDir[i])
于 2013-06-28T19:36:55.397 回答
3

转储“myObject”:

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 序列化程序失败。请参阅如何在 python 中克服“datetime.datetime not JSON serializable”?

于 2014-06-26T16:12:23.437 回答
3

无论您的变量如何在类内、__init__ 内或外部定义,这都有效。

your_obj = YourObj()
attrs_with_value = {attr: getattr(your_obj, attr) for attr in dir(your_obj)}
于 2020-02-03T04:43:56.737 回答
2

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

于 2010-09-13T05:11:22.607 回答
2

试试beeprint

它不仅可以帮助您打印对象变量,还可以帮助您输出美观,如下所示:

class(NormalClassNewStyle):
  dicts: {
  },
  lists: [],
  static_props: 1,
  tupl: (1, 2)
于 2016-09-16T16:12:56.443 回答
2

对于每个挣扎的人

  • vars()不返回所有属性。
  • dir()不返回属性的值。

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

for attr in dir(obj):
        try:
            print("obj.{} = {}".format(attr, getattr(obj, attr)))
        except AttributeError:
            print("obj.{} = ?".format(attr))
于 2017-09-07T11:40:59.290 回答
1

你可以试试 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)
于 2016-03-07T16:41:44.443 回答
1

虽然有很多很好的答案,但这里有一个 1-liner,可以提供属性 AS WELL AS 值:

(str(vars(config)).split(",")[1:])

其中'config'是有问题的对象。我将此列为单独的答案,因为我只想简单地打印对象的相关值(不包括 __main 等)而不使用循环或漂亮的打印并且没有找到方便的答案。

于 2021-10-04T08:04:22.037 回答
1

vars() 似乎显示了该对象的属性,但 dir() 似乎也显示了父类的属性。您通常不需要查看strdoc等继承属性。字典

In [1]: class Aaa():
...:     def __init__(self, name, age):
...:         self.name = name
...:         self.age = age
...:
In [2]: class Bbb(Aaa):
...:     def __init__(self, name, age, job):
...:         super().__init__(name, age)
...:         self.job = job
...:
In [3]: a = Aaa('Pullayya',42)

In [4]: b = Bbb('Yellayya',41,'Cop')

In [5]: vars(a)
Out[5]: {'name': 'Pullayya', 'age': 42}

In [6]: vars(b)
Out[6]: {'name': 'Yellayya', 'age': 41, 'job': 'Cop'}

In [7]: dir(a)
Out[7]:
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 ...
 ...
 '__subclasshook__',
 '__weakref__',
 'age',
 'name']
于 2021-12-18T12:18:38.820 回答
0

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

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

o.keys()

对于这些属性的值:

o.values()
于 2017-05-04T12:53:28.807 回答
0

答案中,可以稍微修改以仅获取对象的“属性”,如下所示:

def getAttributes(obj):
    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 for name in dir(obj) 
            if name[0] != '_' and name not in disallowed_names and hasattr(obj, name)}
    pprint(attributes(obj))

在临时添加此功能时很有帮助,并且无需对现有源代码进行太多更改即可将其删除

于 2021-08-18T05:41:26.980 回答
0

该项目修改 pprint 以显示所有对象字段值,它忽略了对象__repr__成员函数,它还递归到嵌套对象中。它适用于 python3,请参阅https://github.com/MoserMichael/pprintex 您可以通过 pip 安装它:pip install printex

于 2021-09-15T02:04:52.193 回答