Can a Python module use the imports from another file? - python

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

Related

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)>

Structuring a python project

I need to know how to set up the __init__.py and imports in order to structure a python project where I can use fully qualified names throughout the package.
The package will contain a number of sub packages which may contain clashing names. The classes contained within the package will sub class each other and contain references to each other. The project will be generated so the use of fully qualified names would make life a lot simpler.
This sample project represents the structure I am aiming at, but only contains a single sub project, while the IDE seems happy with it fails when its run.
MyPackage/__init__.py
import SubPackage as SubPackage
MyPackage/SubPackage/__init__.py
from .FileB import ClassB
from .FileA import ClassA
MyPackage/SubPackage/FileA.py
from __future__ import absolute_import
import MyPackage
class ClassA(MyPackage.SubPackage.ClassB):
thingA: 'MyPackage.SubPackage.ClassA'
thingB: MyPackage.SubPackage.ClassB
def __init__(self):
self.thingA = None
self.thingB = None
def test(self):
self.thingA = MyPackage.SubPackage.ClassA()
self.thingB = MyPackage.SubPackage.ClassB()
MyPackage/SubPackage/FileB.py
from __future__ import absolute_import
import MyPackage
class ClassB(object):
nextB: 'MyPackage.SubPackage.ClassB'
def __init__(self):
self.nextB= None
def test(self):
self.nextB= MyPackage.SubPackage.ClassB()
test.py
import MyPackage
x = MyPackage.SubPackage.ClassA()
Error
File "C:\temp\Test.py", line 3, in <module>
import GeneratedLx
File "C:\temp\MyPackage\__init__.py", line 1, in <module>
import Bs as Bs
File "C:\temp\MyPackage\SubPackage\__init__.py", line 12, in <module>
from .FileA import ClassA
File "C:\temp\MyPackage\SubPackage\FileA.py", line 5, in <module>
class ClassA(MyPackage.SubPackage.ClassB):
AttributeError: module 'MyPackage' has no attribute 'SubPackage'
You already cannot have name conflicts at the SubPackage level, so adding MyPackage is entirely redundant, and doesn't work quite the way you're trying to use it. This may be due to when names are bound or something else, but ultimately there should be no instance when you need it. This leaves you to slightly edit the files: "FileA.py", and "FileB.py":
FileA.py
from __future__ import absolute_import
from MyPackage import SubPackage
class ClassA(SubPackage.ClassB):
thingA: 'SubPackage.ClassA'
thingB: SubPackage.ClassB
def __init__(self):
self.thingA = None
self.thingB = None
def test(self):
self.thingA = SubPackage.ClassA()
self.thingB = SubPackage.ClassB()
FileB.py
from __future__ import absolute_import
from MyPackage import SubPackage
class ClassB(object):
nextB: 'SubPackage.ClassB'
def __init__(self):
self.nextB= None
def test(self):
self.nextB= SubPackage.ClassB()
The import statement is also equivalent to from .. import Subpackage using relative imports rather than absolute if desired. Stylistically I tend to use relative imports to help me quickly pick out which imports are part of my project, and which ones are external dependencies.

How to import only functions in a script with custom package/module in Python?

I'm building a package and a noticed that when I import the submodules, they include all of the built-ins that I've imported as well. Is there a way to get around this so when I navigate the submodule with tab complete only the functions and objects from the script are present?
For example, when I import examplemodule.submodule to only see function_i_want when I'm navigating the package contents?
Directory structure
examplemodule
| __init__.py
| submodule
| __init__.py
| submodule.py
examplemodule | submodule | submodule.py
from collections import *
def function_i_want():
return True
Here's an example of what I can import from the module:
>>> import examplemodule
>>> from examplemodule import submodule
>>> submodule.
submodule.AsyncGenerator( submodule.MappingView(
submodule.AsyncIterable( submodule.MutableMapping(
submodule.AsyncIterator( submodule.MutableSequence(
submodule.Awaitable( submodule.MutableSet(
submodule.ByteString( submodule.OrderedDict(
submodule.Callable( submodule.Reversible(
submodule.ChainMap( submodule.Sequence(
submodule.Collection( submodule.Set(
submodule.Container( submodule.Sized(
submodule.Coroutine( submodule.UserDict(
submodule.Counter( submodule.UserList(
submodule.Generator( submodule.UserString(
submodule.Hashable( submodule.ValuesView(
submodule.ItemsView( submodule.defaultdict(
submodule.Iterable( submodule.deque(
submodule.Iterator( submodule.function_i_want(
submodule.KeysView( submodule.namedtuple(
submodule.Mapping( submodule.submodule
When you say from x.y import * you are importing everything defined in __all__ from the module y that resides in directory x.
If you'd only like to import a subset of y you can do the following:
Limit what you're importing from your script
from examplemodule.submodule import function_i_want
or
from examplemodule.submodule import (
function_i_want,
other_function_i_want
)
Define __all__ in your __init__.py
__all__ = ['function_i_want', 'other_function_i_want']
what you could do is import just the module e.g.
import examplemodule
examplemodule.submodule
what this does is only calls the function if you write the module first then .submodule. this is also good if you have more than one module

Django/Python: Import once, use everywhere

I have the following structure for my views directory.
views
|--__init__.py
|--a_management.py
|--b_management.py
|--c_management.py
|--d_management.py
|--e_management.py
and __init__.py starts with the following:
from a_management import *
from b_management import *
from c_management import *
from d_management import *
from e_management import *
.........
...etc...
.........
In each of the files (a_management.py,b_management.py...) I need to write the same code importing modules:
import sys,os
from django.shortcuts import render, redirect
from django.http import HttpResponseRedirect
.........
...etc...
.........
Is it possible to perform all the module imports only in __init__.py?
When I tried, it still seems like the imports are not found and I get errors like: NameError: global name 'sys' is not defined
If each management module needs access to sys, then they all must import it. No way around that. (And really, if they all need it, then they all should import it. It's not a bad thing.)
You could save a bit of typing by having __init__ import sys, os and whtever else is needed, and then each management module can do from __init__ import *, thus "inheriting" all the imported modules from __init__.
Well, except you can't do it this way, because __init__ already imports stuff from the management modules, so the above suggestion would result in circular imports, which are a no-no.
I don't know the specifics of your application, but I have to believe that there's a better way to organize your modules to avoid so much repeated importing, and especially so much use of import *. Generally you want to use that as little as possible.
What about using a shared script to do all the system imports?
BTW, I agree that import * is not the greatest of idea. It makes sense in my use of importer, but I am not so sure in your general setup. Also, you need to careful about circular imports.
So, my answer is specifically only geared towards I need to write the same code importing modules:, not towards whether your setup as a whole makes sense.
Proof of concept, importer is what you really care about.:
├── pack
│ ├── __init__.py
│ ├── importer.py
│ ├── mgmt_1.py
│ ├── mgmt_2.py
└── test.py
test.py
import pack
pack.foo_1()
pack.foo_2()
init.py
from mgmt_1 import *
from mgmt_2 import *
mgmt_1.py
from .importer import *
print "sys", sys
print "os", os
def foo_1():
print "foo_1"
mgmt_2.py:
from .importer import *
print "sys", sys
print "os", os
def foo_2():
print "foo_2", dir(sys)[0:5]
importer.py
import sys
import os
output:
sys <module 'sys' (built-in)>
os <module 'os' from '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
sys <module 'sys' (built-in)>
os <module 'os' from '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
foo_1
foo_2:sys ['__displayhook__', '__doc__', '__excepthook__', '__name__', '__package__']

Python: Load module by its name

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

Categories

Resources