__str__ not enough arguments for format string - python

Hello I'm having trouble with the __str__ when I try to print my object. The interpreter is telling me "TypeError: not enough arguments for format string"
This is the code that I'm trying to run!
'My Practice Class'
class Directory:
'A Simple Directory Class'
def __init__(self, name, parent):
self.name = name
self.parent = parent
def __str__(self):
return 'I am %s a Child directory of %s' % (self.name, self.parent)
def __repr__(self):
return 'Directory(%r)' % self.name
print a
Traceback (most recent call last):
File "<\stdin>", line 1, in <\module>
File "myclass.py", line 14, in \__str\__
def \__repr\__(self):
TypeError: not enough arguments for format string
Thank you

[Moved from comments as this might be a helpful sign post question]
If you are importing a module that you are working on calling
import xxx
a second time does not re-import the changed file (python is trying to be clever, sees you already have that module loaded short-circuts the process). What was going on was that you were changing the file, but python was never seeing those changes.
To reload a module call
reload(xxx)
Also becareful if you imported things as
from xxx import yyy
Calling reload xxx will not affect yyy you would need to do
reload(xxx)
yyy = xxx.yyy

Seems to work fine for me:
>>> class Directory:
'A Simple Directory Class'
def __init__(self, name, parent):
self.name = name
self.parent = parent
def __str__(self):
return 'I am %s a Child directory of %s' % (self.name, self.parent)
def __repr__(self):
return 'Directory(%r)' % self.name
>>> a = Directory('Name', 'Parent')
>>> print(a)
I am Name a Child directory of Parent
>>>
>>>

Related

python get class object instance from another python file

I'm pretty new to python and classes so please excuse me if this is obvious!
I have a class object that I run at start up, however I would like to access that instance of the running class from another .py file
How would I go about this?
here is an example of my code:
class testclass(xml):
instanceobject = 0
def __new__(cls):
return super(testclass, cls).__new__(cls, 'xmlfile', dir1, dir2)
def __init__(self):
super(testclass, self).__init__()
testclass.instanceobject = self
print "print from class init", testclass.instanceobject
then from my other .py file, I try do the following:
from py1file import testclass
print "print from other py file", testclass.instanceobject
and I'm getting the following:
print from class init
<py1file.testclass object at 0x22F7FA80>
print from other py file
0
Basically I want to call a function from the instance of the running class but I need to pass the instance object so I'm trying to get that so I can pass the instance.
Thank you in advanced!

Method takes no arguments [duplicate]

This question already has answers here:
class method with no arguments produces TypeError
(3 answers)
Closed 6 years ago.
class Person:
def __init__(self, name):
self.name = name
def printName():
print "my name is %s" % self.name
Mitchell = Person("Mitchell")
Mitchell.printName()
This code throws this error:
Traceback (most recent call last):
File "/home/mitch/Desktop/test.py", line 8, in <module>
Mitchell.printName()
TypeError: printName() takes no arguments (1 given)
I'm sure I did this correctly...
you missed the self param in the printName function definition
class Person:
def __init__(self, name):
self.name = name
def printName(self):
print "my name is %s" % self.name
Because you forgot to add self explicitly to printName instance method. It should have been like
def printName(self):
...
Python implicitly passes object instance to every instance method. Although not directly related to the question, try to use pep8 conventions when you are working with Python. According to pep8 function names are snake-cased not camel-cased and so are variable names. So use print_name and `mitchell' instaed of their camel and pascel-cased counterparts.

Use only class name without namespace in isinstance

This works in a script to recognise if a is of class myproject.aa.RefClass
isinstance(a, myproject.aa.RefClass)
But how could I do it so I do not have to specify the full namespace ? I would like to be able to type:
isinstance(a, RefClass)
How is this done in Python ?
EDIT: let me give more details.
In module aa.referencedatatable.py:
class ReferenceDataTable(object):
def __init__(self, name):
self.name = name
def __call__(self, f):
self._myfn = f
return self
def referencedatatable_from_tag(tag):
import definitions
defn_lst = [definitions]
for defn in defn_lst:
referencedatatable_instance_lst = [getattr(defn, a) for a in dir(defn) if isinstance(getattr(defn, a), ReferenceDataTable)]
for referencedatatable_instance in referencedatatable_instance_lst
if referencedatatable_instance.name == tag
return referencedatatable_instance
raise("could not find")
def main()
referencedata_from_tag("Example")
In module aa.definitions.py:
from aa.referencedatatable import ReferenceDataTable
#ReferenceDataTable("Example")
def EXAMPLE():
raise NotImplementedError("not written")
For some reason calling the main from aa.referencedatatable.py will throw as it will not be able to recognise the instance of the class. But if I copy this main in another module it will work:
import aa.referencedatatable
a = aa.referencedatatable.referencedatatable_from_tag("Example")
print a
This second example works, for some reason calling this function inside the same module where the class is declared does not.
The 'namespace' is just a module object, and so is the class. You can always assign the class to a different name:
RefClass = myproject.aa.RefClass
or better yet, import it directly into your own namespace:
from myproject.aa import RefClass
Either way, now you have a global name RefClass that references the class object, so you can do:
isinstance(a, RefClass)

Python use destructor in a memory safe way

I have a class that represents a database connection, that has a close method. To make it more comfortable to use, the class itself is a context manager that closes the connection when finished working with it.
The problem is that I got no guarantee that the user of this class will always remember to either use the context manager or close it explicitly, so I would like to implement a method to be called when the object is garbage collected.
The __del__ method looks pretty much like what I need, but I have read in many places that it is risky since it can disturb the garbage collector, especially if there are some circular references.
How true is that? will the following code entail some potential memory leaks?
def __del__(self):
self.close()
Here's an example where you would need the weakref so the child doesn't block the parent from cleaning up:
import weakref
class Spam(object):
def __init__(self, name):
self.name = name
def __del__(self):
print '%r got deleted' % self
def __repr__(self):
return '<%s:%s>' % (self.__class__.__name__, self.name)
class SpamChild(Spam):
def __init__(self, name, parent):
Spam.__init__(self, name)
self.parent = weakref.ref(parent)
def __del__(self):
print '%r, child of %r got deleted' % (self, self.parent)
a = Spam('a')
b = SpamChild('b', a)
del a

How do I get the name of the class containing a logging call in Python?

If I want the function name I can simply include %(funcName)s in the Formatter. But how do I get the name of the class containing the logging call instead?
I've gone through the documentation for logging, but I can't find any mentioning of it.
For a rather easy, pythonic way to get the class name to output with your logger, simply use a logging class.
import logging
# Create a base class
class LoggingHandler:
def __init__(self, *args, **kwargs):
self.log = logging.getLogger(self.__class__.__name__)
# Create test class A that inherits the base class
class testclassa(LoggingHandler):
def testmethod1(self):
# call self.log.<log level> instead of logging.log.<log level>
self.log.error("error from test class A")
# Create test class B that inherits the base class
class testclassb(LoggingHandler):
def testmethod2(self):
# call self.log.<log level> instead of logging.log.<log level>
self.log.error("error from test class B")
testclassa().testmethod1()
testclassb().testmethod2()
By naming the logger as above, the %(name)s will be the name of your class
example output
$ python mymodule.py
[2016-02-03 07:12:25,624] ERROR [testclassa.testmethod1:29] error from test class A
[2016-02-03 07:12:25,624] ERROR [testclassb.testmethod2:36] error from test class B
Alternative(s)
Non-inheritance
import logging
def log(className):
return logging.getLogger(className)
class testclassa:
def testmethod1(self):
log(self.__class__.__name__).error("error from test class A")
class testclassb:
def testmethod2(self):
log(self.__class__.__name__).error("error from test class B")
testclassa().testmethod1()
testclassb().testmethod2()
You should use extra argument:
views.py
import logging
class SampleClass():
def sample_func(self):
logging.getLogger('info_logger').info('some text', extra={'className': self.__class__.__name__})
logger_settings.py
'format': '%(className)s | %(message)s ',
output log:
INFO | SampleClass | "some text"
There is almost certainly a better way of doing this, but until someone points that out, this will work:
import inspect
class testclass:
def testmethod(self):
log()
def log():
stack = inspect.stack()
try:
print "Whole stack is:"
print "\n".join([str(x[4]) for x in stack])
print "-"*20
print "Caller was %s" %(str(stack[2][4]))
finally:
del stack
testclass().testmethod()
The output of this is the following:
Whole stack is:
[' stack = inspect.stack()\n']
[' f()\n']
['testclass().testmethod()\n']
[' exec code in self.locals\n']
[' ret = method(*args, **kwargs)\n']
None
--------------------
Caller was ['testclass().testmethod()\n']
Yet another approach if you also want the module name:
class MyClass(object):
#property
def logger(self):
return logging.getLogger(f"{__name__}.{self.__class__.__name__}")
def what(self, ever):
self.logger.info("%r", ever)
I personally just tend to name my loggers after classes, as it makes it much easier to track down where a particular message came from. So you can have a root logger named "top", and for the module "a" and class "testclass", I name my logger "top.a.testclass".
I don't see the need to otherwise retrieve the classname, since the log message should give you all the information you need.
#ed's response above, it feels very unpythonic to me and it is not something I would be comfortable with using on production code.
This is a function to make an informative log message using the representation class method:
https://docs.python.org/3/library/functions.html#repr
def log_message(thing: object = None, message: str = '') -> str:
""":returns: detailed error message using reflection"""
return '{} {}'.format(repr(thing), message)
This can be implemented to any class using a mix-in:
class UtilMixin(object):
def log(self, message: str = '') -> str:
""":returns: Log message formatting"""
return log_message(thing=self, message=message)
You can than be associated with a class using multiple inheritance:
class MyClass(object, UtilMixin):
def __repr__(self) -> str:
return '<{}>'.format(self)
pass
Usage
logger.warning(self.log('error message goes here'))

Categories

Resources