Same imports across different files - python

Is it possible to include libraries/packages in only one location?
class Sample( db.Model ):
randomText = db.StringProperty( multiline = True )
--
from google.appengine.ext import db
from project.models import Sample
class SampleHandler( ):
def get( self ):
xamp = Sample.all( )
Since the handler already imports db from the google.appengine.ext library/package, and then imports the model i'd assume you don't have to include it again in the model itself. However, it looks like I have to, any way?
Anyone care to explain?

You need to import modules where they are used.
If your models module uses the google.appengine.ext.db module, you need to import it there, not in your handler module.
Importing things creates a reference to that 'thing' in your module namespace, so that the code there can find it when using it. db is the local name by which you get to use the object defined in google.appengine.ext.
If your handler uses the same object, it needs to import that still. If by importing models all names used by models suddenly where available in your handler module too, you'd end up with name conflicts and hard-to-debug errors all over the place.
Vice versa, if only importing google.appengine.ext.db in your handler module and not in your models module were to work, you'd need to import all the dependencies of given module together with the module itself. This quickly becomes unworkable, as you'd need to document all the things your models module requires just to be able to use it.

Related

In Django, why i cannot import a model in an python file created by me in inside the same app?

I created in Django, in my app an python file for forms and I want to import a model from .models (from the same app).
The problem is when I import the model, it returned an error.
The model is(models.py):
class Article(models.Model):
title = models.CharField(max_length=100)
location=models.CharField(max_length=120,null=True,blank=True)
category=models.CharField(max_length=100,null=True,blank=False)
slug=models.SlugField(null=True, blank=True, unique=True)
boddy=models.TextField()
timestamp = datetime.now()
update = models.TimeField(auto_now=True)
The problem is in util.py (the python file that i created) :
from .models import Article
The error is:
ImportError: cannot import name 'Article' from partially initialized module 'hello.models' (most likely due to a circular import) (D:\Python\Django\Projects\myproject\hello\models.py)
The python files are in the same app
It seems you're trying to do what is called a 'Circular Import'; you can't do that.
Your App is separated in modules and packages. (.py files and folders with a __init__.py file inside), and when you import a module into another module, python will run that entire module and set it into memory.
If in models.py you run
from ./.. import utils
... and in utils.py
from .models import Article
You will end up importing a module into another then into another recursively, resulting in a Memory Overflow.
To prevent that from happening, Django comes with a few checks that prevent that circular import.
A good way to prevent that is to separate your classes into smaller modules, so you only import that module.
On the other hand, if you're to refer to Foreign Keys, you can use Django built-in Lazy Reference by using '<app_name>.<ClassName>' under quotes.
By doing so, you don't have to import the module, hence, there's no risk of circular import.

Is it a bad practice (anti-pattern) to provide a module as an argument when initialising a class?

I've a implemented a BaseScanner inside common/base/scanner.py that is subclasses by Scanner inside stash/scanner.py, jira/scanner.py, etc.
Now, the problem is that BaseScanner needs to access the ORM models in e.g. stash/db/models.py, depending on where it's subclasses (in stash, jira, etc.):
# common package
common/base/scanner.py
# stash package
stash/scanner.py
stash/db/models.py
# jira package
jira/scanner.py
jira/db/models.py
...
Is it an anti-pattern to provide a module as an argument to a class when instantiating it, like I do here in main.py?
import stash, jira
...
if args.command == 'stash':
import stash.db.models as models
scanner = jira.Scanner(args, models, ...)
scanner.run()
and then to access the different ORM models from inside BaseScanner, like self.models.Scan, self.models.Match, etc.?
If it's an anti-pattern, what could an alternative solution be?

SQLAlchemy creating two databases in one file with two different models

I want to initialize two databases with total different models in my database.py file.
database.py
engine1 = create_engine(uri1)
engine2 = create_engine(uri2)
session1 = scoped_session(sessionmaker(autocommit=False,autoflush=False,bind=engine1))
session2 = scoped_session(sessionmaker(autocommit=False,autoflush=False,bind=engine2))
Base = declarative_base(name='Base')
Base.query = session1.query_property()
LogBase = declarative_base(name='LogBase')
LogBase.query = session2.query_property()
and the two model structures:
models.py
class MyModel(Base):
pass
models2.py
class MyOtherModel(LogBase):
pass
back to the database.py where i want to create/initialize the databases after importing the models
# this does init the database correctly
def init_db1():
import models
Base.metadata.create_all(bind=engine1)
# this init function doeas not work properly
def init_db2():
import models2
LogBase.metadata.create_all(bind=engine2)
if I change the import in the second init function it does work
def init_db2():
from models2 import *
LogBase.metadata.create_all(bind=engine2)
but there is a warning:
database.py:87: SyntaxWarninyntaxWarning: import * only allowed at module level
Everthing does work properly, I have the databases initialized, but the Warning tells me, that there is something wrong with it.
If someone can explain me why the first attempt isn't correct I would be grateful. Thanks.
You are indeed discouraged from using the from ... import * syntax inside functions, because that makes it impossible for Python to determine what the local names are for that function, breaking scoping rules. In order for Python to make things work anyway, certain optimizations have to be disabled and name lookup is a lot slower as a result.
I cannot reproduce your problem otherwise. Importing just models2 makes sure that everything defined in that module is executed so that the LogBase class has a registry of all declarations. There is no reason for that path to fail while the models.py declarations for Base do work.
For the purposes of SQLAlchemy and declarative table metadata, there is no difference between the import models2 and the from models2 import * syntax; only their effect on the local namespace differs. In both cases, the models2 top-level code is run, classes are defined, etc. but in the latter case then the top-level names from the module are added to the local namespace as direct references, as opposed to just a reference to the module object being added.

Python manage classes in separate files

I have a project which uses the MVC pattern.
In folder "models" I have quite many classes, each class is now has its own file. But I feel like it's not convenient, because every time I need to use a class I have to import it separately. E.g. I have many of the followings in my app source:
from models.classX import classX
from models.classY import classY
If I want to import everything at once, something like from models import * I found that I can put all sorts of import in models/__init__.py. But is it the pythonic way to do it ? What is the convention ?
Python is not java; please avoid the one-file-per-class pattern. If you can't change it, you can import all of them from a submodule of your models package:
# all.py: convenient import of all the needed classes
from models.classX import classX
from models.classY import classY
...
Then in your code you can write:
import my.package.models.all as models # or from my.package.models.all import *
and proceed to use models.classX, models.classY, etc.
Most pythonic way is one that you're already using. You can alleviate importing by grouping your classes in modules. For example, in Django usually all application models are in a single file.
From python docs:
Although certain modules are designed to export only names that follow certain patterns when you use import *, it is still considered bad practise in production code.
Firstly, you should rename your classes and modules so that they don't match, and follow PEP8:
models/
classx.py
class ClassX
classy.py
class ClassY
Then, I'd got with this in models/__init__.py:
from models.classx import ClassX
from models.classy import ClassY
Meaning in your main code, you can do any one of:
from models import *
x = ClassX()
from models import ClassX
x = ClassX()
import models
x = models.ClassX()

Python - Dynamic class import

I have the following folder structure:
- MyProject
- App1
- some_module1.py
- some_module2.py
- App2
- some_other_module1.py
- some_other_module2.py
Inside each of the modules (some_module1.py for example) there is a class that extends from a base class, in my case, Producer.
What I am trying to do is dynamically load in this class. To do that, I have a list of "installed apps" that looks like this:
INSTALLED_APPS = (
'App1',
'App2',
)
I am trying to write a function that will check each "app" package for a particular producer class and ensure it extends from the producer base class. Something like this:
module_class = 'some_module1.SomeClass'
# Loop through each package in the INSTALLED_APPS tuple:
for app in INSTALL_APPS:
try:
#is the module_class found in this app?
#App1.some_module1.SomeClass - Yes
#App2.some_module1.SomeClass - No
# is the class we found a subclass of Producer?
exception ImportError:
pass
I've tried experimenting with imp and importlib, but it doesn't seem to handle this kind of import. Is there anyway for me to be able to achieve this?
You may want to have a look at:
__import__() to import modules knowing their name as string;
dir() to get the names of all the objects of a module (attributes, functions, etc);
inspect.isclass(getattr(<module ref>, <object name>)) to identify classes among the objects of a module;
issubclass() to identify sub-classes from a given class, as explained here.
With these tools, you can identify all classes in a given module, that are inheriting a given class.
I'm using this mechanism to dynamically instantiate classes from given module, so that their updates are automatically taken into account at an upper level.

Categories

Resources