python - هل توجد وظيفة مضمنة لطباعة كل الخصائص والقيم الحالية لكائن؟




debugging introspection pretty-print python-datamodel (19)

لطباعة الحالة الحالية للكائن ، يمكنك:

>>> obj # in an interpreter

أو

print repr(obj) # in a script

أو

print obj

__str__ تحدد أساليب __repr__ أو __repr__ . من وثائق بايثون :

__repr__(self) بواسطة الدالة repr() المضمنة وعبر سلسلة التحويلات (علامات الاقتباس العكسي) لحساب تمثيل السلسلة "الرسمي" لكائن ما. إذا كان ذلك ممكنًا ، فيجب أن يبدو هذا مثل تعبير Python صالح يمكن استخدامه لإعادة إنشاء كائن بنفس القيمة (مع توفير بيئة مناسبة). إذا لم يكن ذلك ممكناً ، يجب إرجاع سلسلة من النموذج "<... ... بعض وصف مفيد ...>". يجب أن تكون قيمة الإرجاع كائن سلسلة. إذا __str__() فئة repr () ولكن ليس __str__() ، __repr__() أيضًا استخدام __repr__() عند طلب تمثيل سلسلة "غير رسمي" __repr__() هذه الفئة. يُستخدم هذا عادةً للتصحيح ، لذا من المهم أن يكون التمثيل غنيًا بالمعلومات ولا لبس فيه.

__str__(self) الدالة str() المضمنة وبيان الطباعة لحساب تمثيل السلسلة "غير الرسمي" لكائن ما. هذا يختلف عن __repr__() في أنه ليس من الضروري أن يكون تعبير بايثون صحيح: يمكن استخدام تمثيل أكثر ملاءمة أو موجزة بدلا من ذلك. يجب أن تكون قيمة الإرجاع كائن سلسلة.

ما أبحث عنه هنا هو شيء مثل وظيفة print_r في PHP. هذا حتى يمكنني تصحيح البرامج النصية الخاصة بي من خلال رؤية ما هي حالة الكائن المعني.


إذا كنت تستخدم هذا لتصحيح الأخطاء ، وتريد فقط تفريغ متكرر لكل شيء ، فإن الإجابة المقبولة غير مرضية لأنها تتطلب أن تكون الفصول الدراسية لديك __str__ تطبيقات __str__ جيدة بالفعل. إذا لم يكن الأمر كذلك ، فهذا يعمل بشكل أفضل:

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

يحتوي pprint على "طابعة جميلة" لإنتاج pprint جمالياً لهياكل البيانات الخاصة بك. ينتج المنسق تمثيلات لهياكل البيانات التي يمكن تحليلها بشكل صحيح بواسطة المترجم ، كما يسهل على الإنسان قراءتها. يتم الاحتفاظ بالمخرج على سطر واحد ، إن أمكن ، ويتم وضع مسافة بادئة عند تقسيمه عبر أسطر متعددة.


قد يكون من المفيد التدقيق بها --

هل هناك بايثون مكافئ لبيانات بيرل :: Dumper؟

توصيتي هي -

https://gist.github.com/1071857

لاحظ أن perl يحتوي على وحدة نمطية تسمى Data :: Dumper تقوم بترجمة بيانات الكائن مرة أخرى إلى رمز perl المصدر (NB: لا يترجم الشفرة إلى المصدر ، وغالبًا ما لا تريد وظائف أسلوب الكائن في الإخراج). يمكن استخدام هذا للمثابرة ، ولكن الغرض المشترك هو تصحيح الأخطاء.

هناك العديد من الأشياء التي لا تحققها pipthon pitthon القياسية ، على وجه الخصوص أنها تتوقف عن الانحدار عندما ترى مثيلًا من كائن وتعطيك المؤشر السداسي الداخلي للكائن (errr ، ذلك المؤشر ليس مجموعة كبيرة من الاستخدام بواسطة الطريقة). إذاً ، باختصار ، إن python هو كل شيء عن هذا النموذج الرائع الموجه للكائن ، لكن الأدوات التي تخرجها من الصندوق مصممة للعمل مع شيء آخر غير الأشياء.

يسمح لك Dlle Data :: Dumper بالتحكم في العمق الذي تريده ، كما يكتشف البنى الدائرية المرتبطة (وهذا أمر مهم حقًا). هذه العملية هي اساسا اسهل في تحقيق بيرل لأن الكائنات لا يوجد لديها سحر خاص يتجاوز نعمة (عملية محددة جيدا عالميا).


تمت الإشارة إلى dir ، ولكن ذلك سيعطيك أسماء السمات فقط. إذا كنت تريد قيمهم أيضًا حاول __dict__.

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

o = O()

هنا هو الإخراج:

>>> o.__dict__

{'value': 3}

لقد غلبت على الجواب الذي ذكر فقط pprint. لكي تكون واضحًا ، إذا كنت تريد مشاهدة جميع القيم في بنية بيانات معقدة ، فافعل شيئًا مثل:

from pprint import pprint
pprint(my_var)

حيث my_var هو متغير اهتمامك. عندما استخدمت pprint (vars (my_var)) لم أحصل على شيء ، والإجابات الأخرى هنا لم تساعد أو كانت الطريقة تبدو طويلة بلا داع. بالمناسبة ، في حالتي الخاصة ، كان الرمز الذي كنت أفحصه يحتوي على قاموس للقواميس.

تجدر الإشارة إلى أنه مع بعض الفئات المخصصة ، قد ينتهي الأمر <someobject.ExampleClass object at 0x7f739267f400> غير مفيد <someobject.ExampleClass object at 0x7f739267f400> نوع من الإخراج. في هذه الحالة ، قد يتعين عليك تنفيذ طريقة __str__ أو تجربة بعض الحلول الأخرى. ما زلت أرغب في العثور على شيء بسيط يعمل في جميع السيناريوهات ، بدون مكتبات الطرف الثالث.


هذا يطبع جميع محتويات الكائن بشكل متكرر في تنسيق 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)

مجرد محاولة beeprint

فهو يساعدك ليس فقط على طباعة متغيرات الكائن ، ولكن أيضًا الإخراج الجميل ، كما يلي:

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

أنت بالفعل تجمع شيئين مختلفين.

استخدم 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__'}

أنا أحب العمل مع أنواع keys الثعبان المدمج في keys أو values .

بالنسبة للسمات بغض النظر عن أنها أساليب أو متغيرات:

o.keys()

لقيم تلك السمات:

o.values()

كنت في حاجة لطباعة معلومات DEBUG في بعض السجلات ولم أتمكن من استخدام pprint لأنها سوف تنكسر. بدلا من ذلك فعلت هذا وحصلت على نفس الشيء تقريبا.

DO = DemoObject()

itemDir = DO.__dict__

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

حاول 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)

يمكنك تجربة شريط الأدوات Flask Debug.
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)

في معظم الحالات ، __dict__ استخدام __dict__ أو dir() إلى الحصول على المعلومات التي تريدها. إذا كنت بحاجة إلى المزيد من التفاصيل ، فستشتمل المكتبة القياسية على وحدة inspect التي تسمح لك بالحصول على قدر كبير من التفاصيل. بعض من nuggests الحقيقي للمعلومات تشمل:

  • أسماء الدالة ومعلمات الأسلوب
  • التسلسل الهرمي الطبقة
  • التعليمات البرمجية المصدر لتنفيذ كائنات وظائف / فئة
  • المتغيرات المحلية من كائن الإطار

إذا كنت تبحث فقط عن "ما هي قيم السمات التي __dict__ الكائن الخاص بي؟" ، فقد تكون dir() و __dict__ على الأرجح كافية. إذا كنت تتطلع حقاً إلى البحث عن الحالة الراهنة للأشياء التعسفية (مع الأخذ في الاعتبار أن كل شيء تقريباً في الثعبان هو شيء) ، فإن inspect يكون جديراً بالاعتبار.


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

لماذا لا شيء بسيط:

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

مثال metaprogramming كائن تفريغ مع السحر :

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

مع الغنوص 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>

إنها عفا عليها الزمن لكن لا تزال تعمل.


لتفريغ "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__ (يجب أن يكون لدى الوسيطة الاستثناءات.الخطاط: Vars () سمة __dict__). لم يكن dir () ما كنت أبحث عنه: إنه مجرد قائمة بأسماء الحقول ، لا يعطي القيم أو بنية الكائن.

أعتقد أن json.dumps () قد يعمل مع معظم الكائنات بدون الافتراضي = json_util.default ، ولكن كان لدي حقل تاريخ / وقت في الكائن بحيث فشل تسلسل json القياسي. راجع كيفية التغلب على "datetime.datetime لا JSON serializable" في python؟


عندما يتم إنشاء مثيل الكائنات ، يتم تمرير الكائن نفسه إلى المعلمة الذاتية.

وبسبب هذا ، يتم ربط بيانات الكائن بالكائن. في ما يلي مثال على الطريقة التي قد ترغب في تصور ما قد تبدو عليه بيانات كل كائن. لاحظ كيف يتم استبدال 'self' باسم الكائنات. لا أقول أن هذا المثال الموضح أدناه دقيق تمامًا ، ولكن نأمل أن يخدم هدفًا في تصور استخدام الذات.

يتم تمرير الكائن إلى المعلمة الذاتية بحيث يمكن للكائن أن يحتفظ ببياناته الخاصة.

على الرغم من أن هذا قد لا يكون دقيقًا تمامًا ، فكر في عملية إنشاء كائن مثل هذا: عندما يتم إنشاء كائن ، فإنه يستخدم الفئة كقالب لبياناته وأساليبه الخاصة. بدون تمرير الاسم الخاص به إلى المعلمة الذاتية ، ستبقى السمات والأساليب في الفئة كقالب عام ولن يتم الرجوع إليها (تنتمي إلى) الكائن. لذا عن طريق تمرير اسم الكائن إلى المعلمة الذاتية ، فهذا يعني أنه إذا تم إنشاء 100 كائن من فئة واحدة ، فيمكنهم جميعًا تتبع بياناتهم وطرقهم الخاصة.

انظر الرسم التوضيحي أدناه:





python debugging introspection pretty-print python-datamodel