python confusion on importing modules - python-3.x

I saw this statement
from django import forms
the folder structure is
django\
__init__.py
forms\
__init__.py
..(continues)
My doubt is instead of the above statement why cant we imports forms like this.
import django.forms
when i tried this in pycharm. it says unused import statement.
the following is my code:
#from django import forms
import django.forms
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'text',)
it gives me error
class PostForm(forms.ModelForm):
NameError: name 'forms' is not defined

From python's docs,
... when using syntax like import item.subitem.subsubitem, each item
except for the last must be a package; the last item can be a module
or a package but can’t be a class or function or variable defined in
the previous item.
Then since its __init__.py designates forms as a package, you should be able to import it via import django.forms. Accessing its members will be different since where before you wrote forms.x now you would write django.forms.x.

Related

Dynamically importing identically named classes from files in subfolder

I need to to dynamically import identically named classes from files in a subfolder. The classes have different implementations in every file. After the import I need to create an instance of each class and store them in a data structure so I can invoke each function in thee instances.
folder structure:
./main.py
./players/player1.py
./players/player2.py
./players/player3.py
./players/player4.py
player1.py
class PlayerClass():
def doStuff():
stuff implementation 1
player2.py
class PlayerClass():
def doStuff():
stuff implementation 2
So main.py will import all PlayerClasses from these files and create once instance each to then be able to call functions like doStuff form each instance.
Something like:
importedClasses[0].doStuff()
I have managed to extract file names but I can't get the import to work from a subfolder and I can't import them as unique objects and store them in a list or similar either.
Here is one approach
from glob import glob
from importlib.machinery import SourceFileLoader
modules = sorted(glob('players/player*.py'))
imported_classes = list(map(lambda pathname: SourceFileLoader(".", pathname).load_module().PlayerClass(), modules))
imported_classes[0].doStuff()
Here we are using glob to match the pathnames to the modules we would like to import. Then import them using the importlib module (SourceFileLoader).

Python: cannot find reference to class when using import

I am new to python. I am using the anaconda prompt to run my code. I am trying to import a class from another module but I keep getting errors such as cannot find reference to the class.
P.S please don't negative mark this, or else I will lose the privilege of asking questions
I have already provided an __init__ function.
The module itself runs just fine.
I have used from parser import Parser
I have used from parser import * statement as well
My Parser class
class Parser(object):
def __init__(self, tokens):
self.tokens = tokens
self.token_index = 0
My main class
from parser import Parser
I expected it to normally import the class, but it is unable to.
I keep getting the cannot import name 'Parser' from 'parser' (unknown location) when I use from parser import Parser
parser is also the name of a Python module in the standard library.
It's likely there is a name conflict, and that Python is importing the module from the standard library.
I changed the module name to mparser and it works!

Make import module return a variable

I would like to make an imported module behave like an object, ie. an dictionary.
E.g.
import module
print(module['key'])
and in module.py
return {'key':'access'}
This is very easy for Class by inheriting from dict, but how do I do this on a module level?
In particular I want to dynamically built the dictionary in module and return it when module is imported.
I know that there are other solutions such as defining the dict as a var in the module workspace and accessing it via module.var, but I am interested if something like this is possible.
As you point out, you can do this with a class, but not with a module, as modules are not subscriptable.Now I'm not going to ask why you want to do this with an import, but it can be done.
What you do is create a class that does what you want, and then have the module replace itself with the class when imported. This is of course a 'bit of a hack' (tm). Here I'm using UserDict as it gives easy access to the dict via the class attr data, but you could do anything you like in this class:
# module.py
from collections import UserDict
import sys
import types
class ModuleDict(types.ModuleType, UserDict):
data = {'key': 'access}
sys.modules[__name__] = ModuleDict(__name__)
Then you can import the module and use it as desired:
# code.py
import module
print(module['key']
# access

questions about importing in python 3

i've seen plenty of importing questions but didn't find any that explained importing very "easily". there are are 3 types of importing that i know of, and none of them seem to do what i'm looking for or would like to do. eg. main.py has def a() def b() class c() and def d() and lets say i have a start.py file.
main:
def a():
print("1")
def b():
print("2")
class c():
def__init__(self,name = "Rick")
self.name = name
def d():
print("4")
so now im my start.py file i want to import everything from them. what is the best way? i have tried using import main and i run into issues after creating an instance of class c [ ricky = c() ]that ricky isn't defined or accessing ricky.name it will say module ricky has no attribute name. so that doesn't seem to work. what is this even used for if you aren't importing the entire main.py file?
then there is from main import a, b, c, d that seems to work just fine, but there really has to be another way than having to import every single function, definition, variable, and everything.
third there is from main import * i'm not sure how this one works, i have read some on it mainly stating there should be an __ all __ = everything i want imported. but where do i put this. at the very top of the page inside my main.py? but there still should be a better way?
is my import main just not working correctly? or do i have to list everything i want to import either in a from main import statement or in an __ all __ list?
does importing carry over to another py file? eg. 1.py 2.py 3.py if inside 2.py i import 3.py correctly and everything works. in 1.py can i just import 2.py and it will import 3.py into 1.py from the import statement inside of 2.py? or do i have to import 2.py and 3.py again into 1.py?
the 3 main imports:
import (pythonfile) aka "module" using this will import all classes and functions to be used. does not import other imports. to call something in the imported module eg. modlue: MAIN, function: FUNC ... to call: MAIN.FUNC()
from module import FUNC, CLASS, .... when using this import you don't need to call it with the module. it is almost as if it is right infront of you eg.
module: MAIN, function: FUNC ..... to call: FUNC()
from module import * a combination of the previous two imports. will import everything from the module to be accessed without calling with the module extention. this form imports other imports as well. so if you have two modules that need to talk to eachother. using this will cause an error since you will be trying to import a module into another module then back into it's self again. A imported into B, A and B imported back into A. it doesn't work. so watch when using. May cause other importing errors of trying to import multiple modules that share imports. eg. importing A and B into C if A and B share D (pending for testing)
from MAIN import * call function: FUNC()
hope this helps other people out who are having issues understanding exactly how importing works and calling your functions/classes and what not.

Mutual imports; difference between import's standart, "from" and "as" syntax

Given this simple folder structure
/main.py
/project/a.py
/project/b.py
main.py is executed by the python interpreter and contains a single line, import project.a.
a and b are modules, they need to import each other. A way to achieve this would be
import project.[a|b]
When working with deeper nested folder structures you don't want to write the entire path everytime you use a module e.g.
import project.foo.bar
project.foo.bar.set_flag(project.foo.bar.SUPER)
Both from project import [a|b] and import project.[a|b] as [a|b] result in an import error (when used in both, a and b).
What is different between the standart import syntax and the from or as syntax? Why is only the standart syntax working for mutual imports?
And more importantly, is there a simple and clean way to import modules that allows mutual imports and assigning shorter names to them (ideally the modules basename e.g. bar in the case of project.foo.bar)?
When you do either import project.a or from project import a, the following happens:
The module object for project.a is placed into sys.modules. This is a dictionary that maps each module name to its module object, so you'll have sys.modules = {..., 'p.a': <module 'p.a' from '.../project/a.py'>, ...}.
The code for the module is executed.
The a attribute is added to project.
Now, here is the difference between import project.a and from project import a:
import project.a just looks for sys.modules['project.a']. If it exists, it binds the name project using sys.modules['project'].
from project import a looks for sys.modules['project'] and then checks if the project module has an a attribute.
You can think of from project import a as an equivalent to the following two lines:
import project.a # not problematic
a = project.a # causes an error
That why you are seeing an exception only when doing from project import a: sys.modules['project.a'] exists, but project does not yet have a a attribute.
The quickest solution would be to simply avoid circular imports. But if you can't, then the usual strategies are:
Import as late as possible. Suppose that your a.py looks like this:
from project import b
def something():
return b.something_else()
Rewrite it as follows:
def something():
from project import b
return b.something_else()
Of course, you would have to repeat imports in all your functions.
Use lazy imports. Lazy imports are not standard feature of Python, but you can find many implementations around. They work by using the "import as late as possible" principle, but they add some syntactic sugar to let you write fewer code.
Cheat, and use sys.modules, like this:
import sys
import project.a
a = sys.modules['project.a']
Very un-pythonic, but works.
Obviously, whatever solution you choose, you won't be able to access the attributes from a or b until the modules have been fully loaded.

Resources