Python - get static information - python

i have to get static information from one 'module' to another. I'm trying to write logger with information about code place from where we're logging.
For example, in some file:
LogObject.Log('Describe error', STATIC_INFORMATION)
Static information is class name, file name and function name.
I get it from this:
__file__
self.__class__.__name__
sys._getframe().f_code.co_name
But i don't want to write this variables during logging. Can i create some function and call it. For example:
LogObject.Log('Describe error', someFunction())
How can i use it for getting static information?

I don't think "static" is the world you're looking for. If I understand you correctly, you want to write a function that will return the filename, class name and method name of the caller.
Basically, you should use sys._getframe(1) to access the previous frame, and work from there.
Example:
def codeinfo():
import sys
f = sys._getframe(1)
filename = f.f_code.co_filename
classname = ''
if 'self' in f.f_locals:
classname = f.f_locals['self'].__class__.__name__
funcname = f.f_code.co_name
return "filename: %s\nclass: %s\nfunc: %s" % (filename, classname, funcname)
Then from a method somewhere you can write
logger.info("Some message \n %s" % codeinfo())

First, please use lower-case names for objects and methods. Only use UpperCase Names for Class definitions.
More importantly, you want a clever introspective function in every class, it appears.
class Loggable( object ):
def identification( self ):
return self.__class__.__module__, self.__class__.__name__, sys._getframe().f_code.co_name
class ARealClass( Loggable ):
def someFunction( self ):
logger.info( "Some Message from %r", self. identification() )
If all of your classes are subclasses of Loggable, you'll inherit this identification function in all classes.

Related

Python class attribute 'is not defined' when referenced by another class attribute

Using the following, I am able to successfully create a parser and add my arguments to self._parser through the __init()__ method.
class Parser:
_parser_params = {
'description': 'Generate a version number from the version configuration file.',
'allow_abbrev': False
}
_parser = argparse.ArgumentParser(**_parser_params)
Now I wish to split the arguments into groups so I have updated my module, adding some classes to represent the argument groups (in reality there are several subclasses of the ArgumentGroup class), and updating the Parser class.
class ArgumentGroup:
_title = None
_description = None
def __init__(self, parser) -> ArgumentParser:
parser.add_argument_group(*self._get_args())
def _get_args(self) -> list:
return [self._title, self._description]
class ArgumentGroup_BranchType(ArgumentGroup):
_title = 'branch type arguments'
class Parser:
_parser_params = {
'description': 'Generate a version number from the version configuration file.',
'allow_abbrev': False
}
_parser = argparse.ArgumentParser(**_parser_params)
_argument_groups = [cls(_parser) for cls in ArgumentGroup.__subclasses__()]
However, I'm now seeing an error.
Traceback (most recent call last):
...
File "version2/args.py", line 62, in <listcomp>
_argument_groups = [cls(_parser) for cls in ArgumentGroup.__subclasses__()]
NameError: name '_parser' is not defined
What I don't understand is why _parser_params do exist when they are referred by another class attribute, but _parser seemingly does not exist in the same scenario? How can I refactor my code to add the parser groups as required?
This comes from the confluence of two quirks of Python:
class statements do not create a new local scope
List comprehensions do create a new local scope.
As a result, the name _parser is in a local scope whose closest enclosing scope is the global scope, so it cannot refer to the about-to-be class attribute.
A simple workaround would be to replace the list comprehension with a regular for loop.
_argument_groups = []
for cls in ArgumentGroup.__subclasses()__:
_argument_groups.append(cls(_parser))
(A better solution would probably be to stop using class attributes where instance attributes make more sense.)

Default property when none matching - Python

I have browsed the web and pydoc to find my answer without success.
My issue is the following:
I want to define a class with properties, as I would do habitually.
class Container(object):
def __init__(self, content):
assert isinstance(content, dict), "The container can only contain a dictionary"
self._content = content
#property
def name():
try:
return self._content["its_name"]
except KeyError:
raise AttributeError
Now, to access the content's field "its_name", I can use container.name, with a slight modification between the field's name and the attribute's.
I would like to have a default behavior when no specific getter property is set.
I mean, if I call container.description, I want my class to try returning self._content["description"], and throw an AttributeError if there is no such key.
While still calling the specific property for cases like container.name.
Thanks in advance for your help.
This is what the __getattr__ special method is for:
def __getattr__(self, attrname):
# Only called if the other ways of accessing the attribute fail.
try:
return self._content[attrname]
except KeyError:
raise AttributeError
Note that if for some reason you try to retrieve an unknown attribute when the _content attribute doesn't exist, the line
return self._content[attrname]
will recursively invoke __getattr__ in an attempt to get the _content attribute, and that call will call __getattr__, and so on until stack overflow.

python defining multiple classes with decorators

I have the base class:
class BaseGameHandler(BaseRequestHandler):
name = 'Base'
def get(self):
self.render(self.name + ".html")
Now, I need to define a few subclasses of this but the thing is, they have to have a decorator. Equivalent code would be:
#route('asteroid')
class AsteroidGameHandler(BaseGameHandler):
name = 'asteroid'
#route('blah')
class BlahGameHandler(BaseGameHandler):
name = 'blah'
and maybe a few more.
A little background here: This is a tornado web app and the #route decorator allows you to map /blah to BlahGameHandler. This code maps /blah to BlahGameHandler and /asteroid to AsteroidGameHandler.
So I thoughtI should use metaprogramming in python and define all these classes on the fly. I tried the following which doesn't work(and by doesn't work I mean the final web-app throws 404 on both /asteroid and /blah):
game_names = ['asteroid', 'blah']
games = list([game, type('%sGameHandler' % (game.title()), (BaseGameHandler,), {'name': game})] for game in game_names)
for i in xrange(len(games)):
games[i][1] = route(games[i][0])(games[i][1])
What am I missing? Aren't these two codes equivalent when run?
The library that you use only looks for global class objects in your module.
Set each class as a global; the globals() function gives you access to your module namespace as a dictionary:
for i in xrange(len(games)):
globals()[games[i][1].__name__] = route(games[i][0])(games[i][1])
The include() code does not look for your views in lists.
To be specific, include() uses the following loop to detect handlers:
for member in dir(module):
member = getattr(module, member)
if isinstance(member, type) and issubclass(member, web.RequestHandler) and hasattr(member, 'routes'):
# ...
elif isinstance(member, type) and issubclass(member, web.RequestHandler) and hasattr(member, 'route_path'):
# ...
elif isinstance(member, type) and issubclass(member, web.RequestHandler) and hasattr(member, 'rest_route_path'):
# ...
dir(module) only considers top-level objects.

How can I get the name of the class of a bound method from the interpreter stack?

I have an awesome little function that looks like this:
def verbose_print(message, *args, **kwargs):
"""Prints `message` with a helpful prefix when in verbose mode
Args:
message (str): The message to print. Can be a format string, e.g.
`A %s with some %s in it`
*args: Variables for the message format
**kwargs: Keyword variables for the message format
"""
# Only print when in verbose mode
if not config.verbose:
return
# Ready a prefix for the message
try:
s = inspect.stack()
module_name = inspect.getmodule(s[1][0]).__name__
func_name = s[1][3]
prefix = '### %s->%s' % (module_name, func_name)
except Exception as e:
prefix = '### [stack unavailable]'
if args:
message = message % args
elif kwargs:
message = message % kwargs
print '%s: %s' % (prefix, message)
The point of the function is that I can call it from anywhere with a message, and if my project config file is set to verbose mode, all the messages will be printed with a helpful prefix to show where it was called. Here's an example of some output:
### avesta.webserver->check_login: Checking login for client at 127.0.0.1
### avesta.webserver->check_login: Found credentials cookie with username: tomas, token: blablabla
### avesta.webserver->check_login: Login valid, refreshing session
### avesta.webserver->get_flash_memory: Fetched flash data: None
### avesta.webserver->get: Fetched data from empty path ('previous_values', 'name'), returning ''
### avesta.webserver->get: Fetched data from empty path ('previous_values', 'description'), returning ''
### avesta.webserver->get: Fetched data from empty path ('validation_errors', 'name'), returning ''
The format is "### module->function: message".
Now most of the time this is really helpful, but it's not perfect. In the example above, the "get" function is actually a bound method of a class, but that's not visible. What I'm trying to accomplish is that when a function is a bound method, I print with this format instead:
"### module->ClassName.function"
But the problem is:
I only get the function name from the stack, so I can't really check if it's a bound method
Even if I had the function reference, how would I extrapolate the class name it's bound to?
Thanks for any answers that can help me figure this out.
I thought this was going to be easy, but it turned out to be a bit complicated. If you have a reference to the bound method, you can get its class name via boundMethod.im_class.__name__. However, when you're grabbing the stack, you can't easily get a reference to the bound method, just to stack frames.
However all is not lost! The inspect module can get you function arguments from a stack frame using the getargvalues function. You do have to cheat a little, by relying on the convention that methods always have their first argument named "self". You can check for that, then grab the "self" value from the function's locals dict, and from there it's easy to get the class name. Try replacing your current try block with his code:
s = inspect.stack()
module_name = inspect.getmodule(s[1][0]).__name__
func_name = s[1][3]
arginfo = inspect.getargvalues(s[1][0])
if len(arginfo.args) > 0 and arginfo.args[0] == "self":
func_name = "%s.%s" (arginfo.locals["self"].__class__.__name__, func_name)
prefix = '### %s->%s' % (module_name, func_name)

Getting error message when trying to attach a class to an object

i have a little problem when i try to attach a class to an object in python. I have a textfile 'file', which is seperated into a list for each line. The program will read every line and print a name and a longname. Imagine that the textfile look like this:
"John '\n' John Travolta" (...)
Here's my bit of code:
class Name:
def __init__(self, name, longname):
self.name=name
self.longname=longname
def __str__(self):
s="Name:"+self.name
s+="\n Longname:"+self.longname
def func():
for line in file:
name=line[:1]
longname=line['\n':]
c=Name(name, longname)
c.func()
I get the error message that my 'name' and 'longname' is not defined but I did this with my function??? :(
It works if I put the function outside the class, like this:
def func():
for line in file:
name=line[:1]
longname=line['\n':]
c=Name(name, longname)
print c
Need help!
You need to assign something to name and longname before you can use them:
name = 'foo'
longname = 'foo bar'
c=Name(name, longname)
c.func()
but I did this with my function?
No.
Firstly, you didn't call your function yet. The function call is after the line that gives the error.
Secondly, the function has its own scope. The name there is different from the global name.
I don't think it makes any sense to move your func method inside the class definition. The code that you said works is a better way to do it.

Categories

Resources