python get module name that declared a variable - python

so classes in python can tell you where they were defined:
# module a.py
class Something:
pass
from a import SomeClass
print(f"name: {SomeClass.__name__}, module: {SomeClass.__module__}")
# name: SomeClass, module: a
I want to know if it is possible to get the module that declared a variable, rather than a class.
# module a.py
SOME_LIST = [1,2,3]
from a import SOME_LIST
# something like this:
print(SOME_LIST.__module__)
# Traceback (most recent call last):
# File "b.py", line 3, in <module>
# print(SOME_LIST.__module__)
# AttributeError: 'list' object has no attribute '__module__'
The use case is that I need to crawl a complicated structure of nested classes and lists across many files and I need to generate namespaces for classes and variables found in this structure.

Related

python classes inheriting from each other

I am having 2 Python files in same directory. one.py and two.py containing classes First and Second respectively. I want import classes and inherit each other and use methods defined in each other.
one.py
from two import Second
class First(Second):
def first(self):
print "first"
two.py
from one import First
class Second(First):
def second(self):
print "second"
while compiling I am getting following error. Is there any way I can overcome this. Please suggest alternative methods also.
Traceback (most recent call last):
File "C:\Users\uvijayac\Desktop\New folder\two.py", line 1, in <module>
from one import First
File "C:\Users\uvijayac\Desktop\New folder\one.py", line 1, in <module>
from two import Second
File "C:\Users\uvijayac\Desktop\New folder\two.py", line 1, in <module>
from one import First
ImportError: cannot import name First
The actual problem you're encountering is that you're trying to do a circular import, which has nothing to do with your circular inheritance. (There's plenty of material on SO on how to avoid that.)
However, note that circular inheritance is also not possible, as a class is only available for subclassing once it's defined, and its definition includes being subclassed from the other class, which therefore also needs to already be defined, which requires... you get the point - you can't have circular inheritance.

Why __import__() is returning the package instead of the module?

I have this file structure (where the dot is my working directory):
.
+-- testpack
+-- __init__.py
+-- testmod.py
If I load the testmod module with the import statement, I can call a function that is declared within:
>>> import testpack.testmod
>>> testpack.testmod.testfun()
hello
but if I try to do the same using the __import__() function, it doesn't work:
>>> __import__("testpack.testmod").testfun()
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
__import__("testpack.testmod").testfun()
AttributeError: 'module' object has no attribute 'testfun'
indeed, it returns the package testpack instead of the module testmod:
>>> __import__("testpack.testmod").testmod.testfun()
hello
How come?
This behaviour is given in the docs:
When the name variable is of the form package.module, normally, the
top-level package (the name up till the first dot) is returned, not
the module named by name. However, when a non-empty fromlist argument
is given, the module named by name is returned.
...
The statement import spam.ham results in this call:
spam = __import__('spam.ham', globals(), locals(), [], -1)
Note how __import__() returns the toplevel module here because this is
the object that is bound to a name by the import statement.
Also note the warning at the top:
This is an advanced function that is not needed in everyday Python
programming, unlike importlib.import_module().
And then later:
If you simply want to import a module (potentially within a package)
by name, use importlib.import_module().
So the solution here is to use importlib.import_module().
It's worth noting that the double underscores either side of a name in Python imply that the object at hand isn't meant to be used directly most of the time. Just as you should generally use len(x) over x.__len__() or vars(x)/dir(x) over x.__dict__. Unless you know why you need to use it, it's generally a sign something is wrong.

NameError when using reload()

I've got file named recommend.py. It has a dict data named critics.
When I try to reload it in the interpreter it gives the following error:
>>> from recommend import critics
>>> reload(recommend.py)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'recommend' is not defined
>>>
I'm new to python. Please help me.
recommend.py is parsed as recommend . py which means that python looks for an object bound to the name recommend and then tries to get the py attribute from it. That doesn't work because you don't have an object named recommend in the current namespace and because even if you did have an object bound to that name, it probably wouldn't have an attribute py.
Of course, you'll need to give reload an actual module object. Something more like:
import recommend
reload(recommend)
reload() takes a module object, not a filename:
import recommend
reload(recommend)

Automatically exporting all functions (vs manually specifying __all__)

I have a helpers.py file which defines about 30 helper functions to be exported as follows:
from helpers import *
To be able to do this, I have added all 30 functions to the __all__ variable. Can I automatically have all functions exported, rather than having to specify each one?
Yes, by simply not specifying __all__.
Actually I think Gandaro is right, you don't have to specify __all__, but if, for some unknown reason, you would have to do it then, you can filter keywords from dir():
__all__ = [ helper for helper in dir() if helper == MY_CONDITION ]
If you don't define __all__ then all of the functions in your module will be imported by calling from helpers import *
If you've got some functions that you'd like to keep private, then you could prefix their names with an underscore. From my testing, this stops the functions from being imported by import *
For example, in helper.py:
def _HiddenFunc():
return "Something"
def AnActualFunc():
return "Hello"
Then:
>>> from helper import *
>>> AnActualFunc()
'Hello'
>>> _HiddenFunc()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '_HiddenFunc' is not defined

Why doesn't this Python work? Simple Oop

class UserDict:
def __init__(self, dict=None):
self.data = {}
if dict is not None: self.update(dict)
I created a file "abc.py" and put above in it.
>>> import abc
>>> d = abc.UserDict()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'UserDict'
Most certainly you are importing the Python abc module for abstract base classes instead of your own abc.py. Better choose a different name for your module.
Edit: Of course it is possible to have your own module with the same name as a built-in module and to import it. You have to make sure that your module is in the interpreter's working directory or set the Python path correctly. But it is much easier to avoid the name clash -- in particular in this case, where you presumably don't care about the module's name anyway.

Categories

Resources