Risposte:
Stai davvero mescolando insieme due cose diverse.
Usa dir()
, vars()
o il inspect
modulo per ottenere ciò che ti interessa (io uso __builtins__
come esempio; puoi invece usare qualsiasi oggetto).
>>> l = dir(__builtins__)
>>> d = __builtins__.__dict__
Stampa quel dizionario come preferisci:
>>> print l
['ArithmeticError', 'AssertionError', 'AttributeError',...
o
>>> 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',
...
La stampa graziosa è disponibile anche nel debugger interattivo come comando:
(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__'}
print re.compile(r'slots').search('No slots here either.').__slots__
inspect
modulo nella tua risposta? Penso che sia la cosa più vicina a print_r o var_dump.
dir()
? dir()
restituisce solo un elenco di nomi e non tutti quelli presenti nell'attributo vars()
o __dict__
.
Vuoi vars()
mescolato con pprint()
:
from pprint import pprint
pprint(vars(your_object))
vars()
restituisce semplicemente il __dict__
suo argomento e questo è anche il fallback dir()
nel caso in cui non vi sia alcun __dir__
metodo. quindi utilizzare dir()
in primo luogo, come ho detto.
dir()
ti dà tutte le cose integrate che probabilmente non ti interessano __str__
e __new__
. var()
non lo fa.
__dict__
attributo.
def dump(obj):
for attr in dir(obj):
print("obj.%s = %r" % (attr, getattr(obj, attr)))
Esistono molte funzioni di terze parti che aggiungono cose come la gestione delle eccezioni, la stampa di caratteri nazionali / speciali, il ricorrere in oggetti nidificati ecc. In base alle preferenze dei loro autori. Ma sostanzialmente si riducono a questo.
getmembers()
funzione nel inspect
modulo standard , ma ho pensato che sarebbe stato più utile in quanto illustra come fare l'introspezione in generale.
__dict__
(come __doc__
e __module__
). Inoltre, __dict__
non funziona affatto per gli oggetti dichiarati con __slots__
. In generale, __dict__
mostra le proprietà a livello di utente che sono effettivamente archiviate in un dizionario internamente. dir () mostra di più.
__dict__
attributo / membro. So che è pazzo, ma vero. Built-in come int
e str
o re.MatchObject
s sono esempi comuni. Prova 'hello'.__dict__
, poi provadir('hello')
dir è stato menzionato, ma questo ti darà solo i nomi degli attributi. Se vuoi anche i loro valori, prova __dict__.
class O:
def __init__ (self):
self.value = 3
o = O()
Ecco l'output:
>>> o.__dict__
{'value': 3}
set
non hanno __dict__
, quindi per loro falliràAttributeError: 'set' object has no attribute '__dict__'
È possibile utilizzare la funzione "dir ()" per fare ciò.
>>> 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']
>>>
Un'altra utile funzione è l'aiuto.
>>> 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
Per stampare lo stato corrente dell'oggetto è possibile:
>>> obj # in an interpreter
o
print repr(obj) # in a script
o
print obj
Per le tue classi definisci __str__
o __repr__
metodi. Dalla documentazione di Python :
__repr__(self)
Chiamato dallarepr()
funzione integrata e dalle conversioni di stringa (virgolette inverse) per calcolare la rappresentazione di stringa "ufficiale" di un oggetto. Se possibile, ciò dovrebbe apparire come un'espressione Python valida che potrebbe essere utilizzata per ricreare un oggetto con lo stesso valore (dato un ambiente appropriato). Se ciò non è possibile, dovrebbe essere restituita una stringa del modulo "<... qualche descrizione utile ...>". Il valore restituito deve essere un oggetto stringa. Se una classe definisce repr () ma non__str__()
,__repr__()
viene utilizzata anche quando è richiesta una rappresentazione di stringa "informale" delle istanze di quella classe. Questo è in genere utilizzato per il debug, quindi è importante che la rappresentazione sia ricca di informazioni e non ambigua.
__str__(self)
Chiamato dallastr()
funzione integrata e dall'istruzione print per calcolare la rappresentazione di stringa "informale" di un oggetto. Ciò differisce dal fatto__repr__()
che non deve essere un'espressione Python valida: al suo posto è possibile utilizzare una rappresentazione più comoda o concisa. Il valore restituito deve essere un oggetto stringa.
print "DEBUG: object value: " + repr(obj)
Potrebbe valere la pena di provarlo --
Esiste un Python equivalente a Data :: Dumper di Perl?
La mia raccomandazione è questa:
https://gist.github.com/1071857
Si noti che perl ha un modulo chiamato Data :: Dumper che traduce i dati degli oggetti in codice sorgente perl (NB: NON traduce il codice in sorgente e quasi sempre non si desidera che il metodo dell'oggetto funzioni nell'output). Questo può essere usato per la persistenza, ma lo scopo comune è il debug.
Ci sono una serie di cose che la pprint python standard non riesce a raggiungere, in particolare smette di scendere quando vede un'istanza di un oggetto e ti dà il puntatore esadecimale interno dell'oggetto (errr, quel puntatore non è molto utile per la via). Quindi, in poche parole, Python è incentrato su questo grande paradigma orientato agli oggetti, ma gli strumenti che ottieni fuori dalla scatola sono progettati per lavorare con qualcosa di diverso dagli oggetti.
Il perl Data :: Dumper ti consente di controllare quanto in profondità vuoi andare, e rileva anche strutture collegate circolari (questo è davvero importante). Questo processo è fondamentalmente più facile da realizzare in perl perché gli oggetti non hanno una magia particolare oltre la loro benedizione (un processo universalmente ben definito).
Raccomando di usare 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__.
Nella maggior parte dei casi, utilizzando __dict__
o dir()
otterrai le informazioni desiderate. Se dovessi avere bisogno di maggiori dettagli, la libreria standard include il modulo inspect , che ti consente di ottenere una quantità impressionante di dettagli. Alcuni dei veri nuggest di informazioni includono:
Se stai solo cercando "quali valori di attributo ha il mio oggetto?", Allora dir()
e __dict__
probabilmente sono sufficienti. Se stai davvero cercando di scavare nello stato attuale di oggetti arbitrari (tenendo presente che in Python quasi tutto è un oggetto), allora inspect
è degno di considerazione.
Esiste una funzione integrata per stampare tutte le proprietà e i valori correnti di un oggetto?
No. La risposta più votata esclude alcuni tipi di attributi e la risposta accettata mostra come ottenere tutti gli attributi, inclusi metodi e parti dell'API non pubblico. Ma non c'è bene completo incorporato la funzione di questo.
Quindi il corollario breve è che puoi scrivere il tuo, ma calcolerà proprietà e altri descrittori di dati calcolati che fanno parte dell'API pubblica e potresti non volerlo:
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))
Osserva l'applicazione della risposta attualmente più votata su una classe con molti tipi diversi di membri dei dati:
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))
stampa solo:
{'baz': 'baz'}
Perché restituisce vars
solo l' __dict__
oggetto di, e non è una copia, quindi se si modifica il dict restituito da Vars, si sta anche modificando __dict__
l'oggetto stesso.
vars(obj)['quux'] = 'WHAT?!'
vars(obj)
ritorna:
{'baz': 'baz', 'quux': 'WHAT?!'}
- il che è negativo perché quux è una proprietà che non dovremmo impostare e non dovrebbe essere nello spazio dei nomi ...
Applicare i consigli nella risposta attualmente accettata (e altri) non è molto meglio:
>>> 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']
Come possiamo vedere, dir
restituisce solo tutto (in realtà solo la maggior parte) dei nomi associati a un oggetto.
inspect.getmembers
, menzionato nei commenti, è ugualmente imperfetto: restituisce tutti i nomi e i valori.
Quando insegno, i miei studenti creano una funzione che fornisce l'API semanticamente pubblica di un oggetto:
def api(obj):
return [name for name in dir(obj) if name[0] != '_']
Possiamo estenderlo per fornire una copia dello spazio dei nomi semantico di un oggetto, ma dobbiamo escludere quelli __slots__
che non sono assegnati e se prendiamo sul serio la richiesta di "proprietà correnti", dobbiamo escludere le proprietà calcolate (come potrebbero diventare costosi e potrebbero essere interpretati come non "attuali"):
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)}
E ora non calcoliamo o mostriamo la proprietà, quux:
>>> attrs(obj)
{'bar': 0, 'baz': 'baz', 'foo': ''}
Ma forse sappiamo che le nostre proprietà non sono costose. Potremmo voler modificare la logica anche per includerli. E forse vogliamo invece escludere altri descrittori di dati personalizzati .
Quindi dobbiamo personalizzare ulteriormente questa funzione. E quindi ha senso che non possiamo avere una funzione integrata che magicamente sa esattamente cosa vogliamo e lo fornisce. Questa è la funzionalità che dobbiamo creare noi stessi.
Non esiste una funzione integrata che lo faccia e dovresti fare ciò che è semanticamente più appropriato per la tua situazione.
FunctionType
. Ma molto utile - grazie!
Un esempio di metaprogrammazione Scarica oggetto con magia :
$ 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
Senza argomenti:
$ python dump.py
<__main__.Data instance at 0x00A052D8>
Con 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>
È un po 'datato ma funziona ancora.
Se lo stai usando per il debug e vuoi solo un dump ricorsivo di tutto, la risposta accettata non è soddisfacente perché richiede che le tue classi abbiano __str__
già buone implementazioni. In caso contrario, funziona molto meglio:
import json
print(json.dumps(YOUR_OBJECT,
default=lambda obj: vars(obj),
indent=1))
TypeError: vars() argument must have __dict__ attribute
Prova 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)
Produzione:
__main__.A(_p = 8, foo = [0, 1, ..., 8, 9], s = 5)
Questo stampa ricorsivamente tutto il contenuto dell'oggetto in formato rientrato json o 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)
Ho votato a favore della risposta che menziona solo la pprint. Per essere chiari, se vuoi vedere tutti i valori in una struttura di dati complessa, fai qualcosa del tipo:
from pprint import pprint
pprint(my_var)
Dove my_var è la variabile di interesse. Quando ho usato non pprint(vars(my_var))
ho ottenuto nulla e altre risposte qui non sono state di aiuto o il metodo sembrava inutilmente lungo. A proposito, nel mio caso particolare, il codice che stavo ispezionando aveva un dizionario di dizionari.
Vale la pena sottolineare che con alcune classi personalizzate potresti finire con un <someobject.ExampleClass object at 0x7f739267f400>
tipo di output inutile . In tal caso, potrebbe essere necessario implementare un __str__
metodo o provare alcune delle altre soluzioni. Mi piacerebbe ancora trovare qualcosa di semplice che funzioni in tutti gli scenari, senza librerie di terze parti.
Avevo bisogno di stampare le informazioni di DEBUG in alcuni registri e non ero in grado di usare pprint perché si sarebbe rotto. Invece l'ho fatto e ho praticamente ottenuto la stessa cosa.
DO = DemoObject()
itemDir = DO.__dict__
for i in itemDir:
print '{0} : {1}'.format(i, itemDir[i])
Per scaricare "myObject":
from bson import json_util
import json
print(json.dumps(myObject, default=json_util.default, sort_keys=True, indent=4, separators=(',', ': ')))
Ho provato vars () e dir (); entrambi hanno fallito per quello che stavo cercando. vars () non ha funzionato perché l'oggetto non aveva __dict__ (exceptions.TypeError: l'argomento vars () deve avere l'attributo __dict__). dir () non era quello che cercavo: è solo un elenco di nomi di campi, non fornisce i valori o la struttura dell'oggetto.
Penso che json.dumps () funzionerebbe per la maggior parte degli oggetti senza default = json_util.default, ma avevo un campo datetime nell'oggetto, quindi il serializzatore json standard non è riuscito. Vedi Come superare "datetime.datetime non JSON serializzabile" in Python?
Perché non qualcosa di semplice:
for key,value in obj.__dict__.iteritems():
print key,value
for key,value in obj.__dict__.iteritems(): print key,value
?
pprint contiene una "bella stampante" per produrre rappresentazioni esteticamente gradevoli delle tue strutture dati. Il formatter produce rappresentazioni di strutture di dati che possono essere analizzate correttamente dall'interprete e sono anche facili da leggere per un essere umano. L'output viene mantenuto su una sola riga, se possibile, e indentato quando suddiviso su più righe.
Prova a essere beeprint .
Ti aiuterà non solo con la stampa delle variabili degli oggetti, ma anche con un bellissimo output, come questo:
class(NormalClassNewStyle):
dicts: {
},
lists: [],
static_props: 1,
tupl: (1, 2)
Per tutti coloro che lottano con
vars()
non restituendo tutti gli attributi. dir()
non restituendo i valori degli attributi.Il codice seguente stampa tutti gli attributi di obj
con i loro valori:
for attr in dir(obj):
try:
print("obj.{} = {}".format(attr, getattr(obj, attr)))
except AttributeError:
print("obj.{} = ?".format(attr))
Puoi provare la barra di debug di 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)
Funziona indipendentemente dal modo in cui le variabili sono definite all'interno di una classe, all'interno di __init__ o all'esterno.
your_obj = YourObj()
attrs_with_value = {attr: getattr(your_obj, attr) for attr in dir(your_obj)}
__dict__
membro (unore.MatchObject
per esempio), ma builtindir()
funziona per tutti gli oggetti.