Python: Load module by its name - python

I'm working on a django project that serves multiple sites; depending on the site I want to import different functionality from a different module; how do I import a module in Python if I have the name of its package and the module name itself as a string?

in Python generally, you can use __import__ builtin function or imp module features:
>>> sys1 = __import__("sys")
>>> import imp
>>> sys2 = imp.load_module("sys2", *imp.find_module("sys"))
>>> import sys
>>> sys is sys1 is sys2
True

Django has its own import function to get an objet from a string. From documentation:
django.utils.module_loading
Functions for working with Python modules.
import_string(dotted_path)
Imports a dotted module path and returns the attribute/class designated by the last name in the path. Raises ImportError if the import failed. For example:
from django.utils.module_loading import import_string
ValidationError = import_string('django.core.exceptions.ValidationError')
is equivalent to:
from django.core.exceptions import ValidationError

Related

ModuleNotFoundError while importing from alias

e.g.
import os as my_os
import my_os.path
ModuleNotFoundError: No module named 'my_os'
but the following script is ok
import os
import os.path
You can't do that in Python.
import statements are importing from Python file names.
You aren't renaming the file of os to my_os, therefore this wouldn't work.
As mentioned in the documentation:
The import statement combines two operations; it searches for the named module, then it binds the results of that search to a name in the local scope.
Tried the similar way as os.py did:
import json as my_json
from my_json.decoder import * # ModuleNotFoundError: No module named 'my_json'
import sys
import json.decoder as my_decoder
sys.modules['my_json.decoder'] = my_decoder
from my_json.decoder import * # it's ok now

Why do *import ...* and *from x import y* idioms behave so differently here?

I have a package structure like this:
- src
- src/main.py
- src/package1
- src/package1/__init__.py
- src/package1/module1.py
- src/package1/module2.py
... where module2 is a subclass of module1, and therefore module1 gets referenced by an absolute import path in module2.py.
That is, in src/package1/module2.py:
from package1.module1 import SomeClassFromModule1
The problem occurs in the main.py script:
## here the imports
def main():
# create an instance of the child class in Module2
if __name__ == "__main__":
main()
Option 1 works. That is, in src/main.py:
from package1.module2 import SomeClassFromModule2
some_name = SomeClassFromModule2()
Option 2 does not work. That is, in src/main.py:
import package1.module2.SomeClassFromModule2
some_name = package1.module2.SomeClassFromModule2()
... causes the following error.
ModuleNotFoundError: No module named 'package1.module2.SomeClassFromModule2'; 'package1.module2' is not a package
So why is there this difference between the import and from ... import idiom?
Would be glad for some clarification.
import x keyword brings all the methods and class from x in the the file it is being called.
from x import y this brings a specific method or class('y' is a method or class) from that .py file ('x' is the file here) instead of bringing all the methods it has.
In your case when you import package1.module2 the SomeClassForModule2() is being already imported and hence you need not write import package1.module2.SomeClassFromModule2
here I guess you want to access a class, so you need to create a object in order to access it.
hope this helped you
After some test, I think you cannot import a function or class by using import your_module.your_class.
It's all about package, module, function and class:
# import module
>>>import os
<module 'os' from ooxx>
#use module of module (a litte weird)
>>>os.path
<module 'posixpath' from ooxx>
#import module of module (a litte weird)
>>>import os.path
#use function
>>>os.path.dirname
<function posixpath.dirname(p)>
# you cannot import a function (or class) by using 'import your.module.func'
# 'import ooxx' always get a module or package.
>>>import os.path.dirname
ModuleNotFoundError
No module named 'os.path.dirname'; 'os.path' is not a package
# instead of it, using 'from your_module import your_function_or_class'
>>>from os.path import dirname
<function posixpath.dirname(p)>

How to import module without class in Python?

I have 4 files in my project:
project/__init__.py
project/app.py
project/mod_x.py
project/mod_y.py
In mod_x.py I have a class (e.g. ModX)
In mod_y.py I have just one function.
I import modules from app.py as follows:
from .mod_x import ModX
import .mod_y
I get an error:
ImportError: No module named 'mod_y'
Before I created init.py I didn't have that kind of problems (of course, I dont put "." before module name).
How to import module which doesn't have the class inside in Python3 with init.py file inside the current directory?
Relative imports are only available for from...import syntax.
You could import that function this way:
from .mod_y import FUNCTION_NAME
Module could be imported this way:
from . import mod_y

Python importlib's analogue for imp.new_module()

PyCharm shows me that imp is deprecated so I wonder if there any analogue of imp.new_module for importlib.
Quoting from documentation (Emphasis mine) -
imp.new_module(name)
Return a new empty module object called name. This object is not inserted in sys.modules.
Deprecated since version 3.4: Use types.ModuleType instead.
Example -
>>> import types
>>> types.ModuleType('name')
<module 'name'>
To show how they are synonymous -
>>> import imp
>>> imp.new_module('name')
<module 'name'>
Python documentation suggests to us:
Note Use importlib.util.module_from_spec() to create a new module if
you wish to set the various import-controlled attributes.
importlib.util.module_from_spec(spec) is preferred over using types.ModuleType to create a new module as spec is used to set as many import-controlled attributes on the module as possible.
To import a Python source file directly, we can use the following snippet:
import importlib.util
import sys
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
spec.loader.exec_module(module)
The example below, we can use to implement lazy imports:
import importlib.util
import sys
def lazy_import(name):
spec = importlib.util.find_spec(name)
loader = importlib.util.LazyLoader(spec.loader)
spec.loader = loader
module = importlib.util.module_from_spec(spec)
sys.modules[name] = module
loader.exec_module(module)
return module
>>> lazy_typing = lazy_import("typing")
>>> #lazy_typing is a real module object,
>>> #but it is not loaded in memory yet.
>>> lazy_typing.TYPE_CHECKING
False

Can a Python module use the imports from another file?

I have something like this:
# a.py
import os
class A:
...
# b.py
import a
class B(A):
...
In class B (b.py) I'd like to be able to use the modules imported in a.py (os in this case). Is it possible to achieve this behavior in Python or should I import the modules in both files?
Edit: I'm not worried about the import times, my problem is the visual clutter that the block of imports puts on the files. I end up having stuff like this in every controller (RequestHandler):
from django.utils import simplejson
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext import db
That's what I'd like to avoid.
Yes you can use the imports from the other file by going a.os.
However, the pythonic way is to just import the exact modules you need without making a chain out of it (which can lead to circular references).
When you import a module, the code is compiled and inserted into a dictionary of names -> module objects. The dictionary is located at sys.modules.
import sys
sys.modules
>>> pprint.pprint(sys.modules)
{'UserDict': <module 'UserDict' from 'C:\python26\lib\UserDict.pyc'>,
'__builtin__': <module '__builtin__' (built-in)>,
'__main__': <module '__main__' (built-in)>,
'_abcoll': <module '_abcoll' from 'C:\python26\lib\_abcoll.pyc'>,
# the rest omitted for brevity
When you try to import the module again, Python will check the dictionary to see if its already there. If it is, it will return the already compiled module object to you. Otherwise, it will compile the code, and insert it in sys.modules.
Since dictionaries are implemented as hash tables, this lookup is very quick and takes up negligible time compared to the risk of creating circular references.
Edit: I'm not worried about the import
times, my problem is the visual
clutter that the block of imports puts
on the files.
If you only have about 4 or 5 imports like that, its not too cluttery. Remember, "Explicit is better than implicit". However if it really bothers you that much, do this:
<importheaders.py>
from django.utils import simplejson
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext import db
<mycontroller.py>
from importheaders import *
Just import the modules again.
Importing a module in python is a very lightweight operation. The first time you import a module, python will load the module and execute the code in it. On any subsequent imports, you will just get a reference to the already-imported module.
You can verify this yourself, if you like:
# module_a.py
class A(object):
pass
print 'A imported'
# module_b.py
import module_a
class B(object):
pass
print 'B imported'
# at the interactive prompt
>>> import module_a
A imported
>>> import module_a # notice nothing prints out this time
>>> import module_b # notice we get the print from B, but not from A
B imported
>>>
You should import it separately. However, if you really need to forward some functionality, you can return a module from a function. Just:
import os
def x:
return os
But it seems like a plugin functionality - objects + inheritance would solve that case a bit better.
Sounds like you are wanting to use python packages. Look into those.
Yep. Once you import a module, that module becomes a property of the current module.
# a.py
class A(object):
...
# b.py
import a
class B(a.A):
...
In Django, for example, many of the packages simply import the contents of other modules. Classes and functions are defined in separate files just for the separation:
# django/db/models/fields/__init__.py
class Field(object):
...
class TextField(Field):
...
# django/db/models/__init__.py
from django.db.models.fields import *
# mydjangoproject/myapp/models.py
from django.db import models
class MyModel(models.Model):
myfield = models.TextField(...)
....
First you can shorten it to:
from django.utils import simplejson
from google.appengine.ext import webapp, db
from webapp import template
Secondly suppose you have those ^ imports in my_module.py
In my_module2.py you can do:
from my_module2.py import webapp, db, tempate
example:
In [5]: from my_module2 import MyMath2, MyMath
In [6]: m2 = MyMath2()
In [7]: m2.my_cos(3)
Out[7]: 0.94398413915231416
In [8]: m = MyMath()
In [9]: m.my_sin(3)
Out[9]: 0.32999082567378202
where my_module2 is:
from my_module import math, MyMath
class MyMath2(object):
the_meaning_of_life = 42
def my_cos(self, number):
return math.cos(number * 42)
and my_module1 is:
import math
class MyMath(object):
some_number = 42
def my_sin(self, num):
return math.sin(num * self.some_number)
Cheers,
Hope it helps
AleP

Categories

Resources