I have very large settings for multiple applications and I want to print this as multi line string. Let me give example (simplified) and explain want I want to achieve and what I get. I think about use of some package to get such nice formatting.
I assume that constructors arguments are same to __dict__
or __slots__
- if not __dict__
or __slots__
is more important to show.
I wrote some formatting library for single line but maybe is better solution with multiline output and more options.
Update (important):
Please not suggest to customize __repr__ or __str__ - I can not or do not want to customize hundred of classes (especially from third party libraries).
class Endpoint:
def __init__(self, host_or_ip: str, port: int):
self.host_or_ip = host_or_ip
self.port = port
class ConnectionSettings:
def __init__(self, endpoints: list[Endpoint]):
self.endpoints = endpoints
class FarmSettings:
def __init__(self, name: str, connection_settings: ConnectionSettings):
self.name = name
self.connection_settings = connection_settings
def main():
settings = FarmSettings(
name='alfa',
connection_settings=ConnectionSettings(
endpoints=[
Endpoint('localhost', 80)
]
)
)
print(settings)
# what I get from default __repr__
#
# <__main__.FarmSettings object at 0x00000203EF713AF0>
#
# what do I want from some method
# FarmSettings(
# name='alfa',
# connection_settings=ConnectionSettings(
# endpoints=[
# Endpoint(name='localhost', port=80)
# ]
# )
# )
if __name__ == '__main__':
main()
CodePudding user response:
You could use e.g. __dict__
to recursively transform your objects to a dictionary, and then use pprint.pprint
or json.dumps
to pretty-print this dictionary:
def dictify(obj):
if isinstance(obj, (int, float, str, bool)):
return obj
if isinstance(obj, (list, tuple)):
return list(map(dictify, obj))
return {"_type": type(obj).__name__,
**{k: dictify(v) for k, v in obj.__dict__.items()}}
settings = FarmSettings(
name='alfa',
connection_settings=ConnectionSettings(
endpoints=[
Endpoint('localhost', 80)
]
)
)
import pprint
pprint.pprint(dictify(settings))
Sample output:
{'_type': 'FarmSettings',
'connection_settings': {'_type': 'ConnectionSettings',
'endpoints': [{'_type': 'Endpoint',
'host_or_ip': 'localhost',
'port': 80}]},
'name': 'alfa'}
Note: The shown function is rudimentary at best. It does not cover many cases of attribute values (e.g. dict
, let alone any kinds of more exotic classes), and it also does not handle cyclic references in your model (i.e. it will run into endless recursion in that case).
CodePudding user response:
Adding the __str__
(or __repr__
) method to your class will allow you to overwrite the output of print(<insert complex object here>)
. For example:
def __str__(self):
return self.<attribute> ...
So, for example, if you had a class like this:
class Person:
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
print(Person("Ryan"))
You get the output:
Ryan