Cannot import from __init__ in a subfolder - python

This is my folder structure:
storage/
__init__.py - contains class StorageAbstract, class DummyStorage, class STORE_TYPE
file.py - contains class FileStorage
db/
__init__.py - contains class DbStorage, class DbStorageAbstract
pg.py - contains class PgStorage
sqlite.py - contains class SQLiteStorage
Classes PgStorage and SQLiteStorage inherit from DbStorageAbstract so I need to import it. I do it like this (in pg.py and sqlite.py) :
from . import DbStorageAbstract
And that throws the following error:
ImportError: cannot import name 'DbStorageAbstract'
However, when I move DbStorageAbstract from storage/db/__init__py. to storage/__init__py and import it like this:
from .. import DbStorageAbstract
then it works fine. I have read this, this and many other resources but still can't figure out what is causing the problem. If it was circular dependence then moving the class to another file would not help I think.
If there is any more information needed, let me know in the comments and I will edit the question.
I am using Python 3.5
EDIT:
Although this question has been identified as a possible duplicate of this question I don't see how it answers my question. Unlike the other question, I already have init files in each folder. If I am wrong please point me to where I can find the answer.
EDIT 2:
This is the db/init.py file:
##################################################################
# Copyright 2018 Open Source Geospatial Foundation and others #
# licensed under MIT, Please consult LICENSE.txt for details #
##################################################################
#import sys
#sys.path.append("/mnt/c/Users/Jan/Documents/GitHub/pywps")
import logging
from abc import ABCMeta, abstractmethod
from pywps import configuration as config
from .. import StorageAbstract
from . import sqlite
from . import pg
LOGGER = logging.getLogger('PYWPS')
class DbStorageAbstract(StorageAbstract):
"""Database storage abstract class
"""
__metaclass__ = ABCMeta
#abstractmethod
def store(self, output):
pass
#abstractmethod
def store_output(self, file_name, identifier):
pass
class DbStorage(StorageAbstract):
def __init__(self):
self.storage = self.get_db_type()
def store(self, output):
assert(self.storage is not None)
self.storage.store(output)
def get_db_type(self):
# get db_type from configuration
try:
db_type = config.get_config_value('db', 'db_type')
except KeyError:
raise exception("Database type has not been specified")
# create an instance of the appropriate class
if db_type == "PG":
storage = pg.PgStorage()
elif db_type == "SQLITE":
storage = sqlite.SQLiteStorage()
else:
raise exception("Unknown database type: '{}'".format(db_type))
return storage

Imports happens before class definition. In db/__init__.py you are importing pg.py, sqlite.py which are depends on classes defined here. To solve it move DbStorageAbstract to another file and if you are going to use it in the same file with pg.py, sqlite.py then make sure import is going to be like this:
from . import dbstorage # this file is the new one contains DbStorageAbstract class
from . import pg, sqlite
Note that if two modules are depends on each other try to create a third module so solve this problem.

I believe you should create another file in your subdirectory
storage/
__init__.py - contains class StorageAbstract, class DummyStorage, class STORE_TYPE
file.py - contains class FileStorage
db/
__init__.py -
pg.py - contains class PgStorage
sqlite.py - contains class SQLiteStorage
base.py contains class DbStorage, class DbStorageAbstract
Then, the pg.py file and sqlite.py file will import the classes like:
from base import DbStorageAbstract
And the __init__.py file will also look like this
from base import DbStorageAbstract, DbStorageAbstract

Related

Python - global class that can be reused

I have a config var in the main class that I use a lot and I also pass it to some other instances that pass it to other classes, and so on.
I need a solution that can be used globally, without the need of passing an instance of the config file, and that I can modify as needed (not const).
something that only requires import anywhere and that the data will be the same and up to date.
In Java, I know that I can Autowired and I know that behind the scenes I'll use the exact same instance.
What solution does Python have?
example
util.py
config = None
setConfig(self, config):
self.config = config
getConfig(self):
return self.config
file1.py
....
import util
util.setConfig(4)
file2.py
import util
util.getConfig()
file3.py
import util
util.setConfig(8)
file4.py
import util
util.getConfig()
main.py
file1()
file2() # ==4
file3()
file4() # ==8
file2() # ==8
Thanks

How to import one class from many classes on one python file

Here is is the directory structure:
->src/dir/classes.py
->src/run.py
# classes.py
class A():
def methA():
# class A
class B():
def MethB():
# class B
class C():
def methC():
# class C
then i need to import Class A in run.py file.
from dir.classes import A
A.methA()
i already tried with using from dir.classes import A but it gives me
ModuleNotFoundError: No module named 'dir.classes'; 'classes' is not a package error
So how can i do that?
You need to put__init__.py file on your dir folder.
This way dir will be recognized as python package.
First, you must have __init__.py in each directory for Python to recognize them as packages.
Then, you should use from dir.classes import A. A is the name of the class, you shouldn't use Class A

'AttributeError: module 'usbiss' has no attribute Aclass' when creating class instance

Trying to write a python package and I cant create an instance of a class in one of my source files.
package layout is:
-packagedir
----README.md
----setup.py
----packagename
--------__init__.py
--------package.py
--------modules
------------file1.py
------------file2.py
in init.py within packagename i have:
from . modules import file1
from . modules import file2
The file file1.py contains a class:
class File1():
def __init__(self):
self.val = 0
# Other methods and such
The file file2.py contains a class:
class File2():
def __init__(self):
self.type = 0
# Other methods and such
and in package.py I have a class as thus:
class Aclass(file1.File1, file2.File2):
def __init__(self):
# nothing important in here yet
I have build and installed my package like this:
python3 setup.py sdist
sudo pip3 install dist/package-0.1.tar.gz
Now I create a file called test.py and put in it the following:
import package
iss = package.Aclass()
when I run the test file i get the following error:
AttributeError: module 'usbiss' has no attribute 'Aclass'
I do not understand why it is that python is not letting me create an instance of class Aclass and thinks I am accessing an attribute. I am sure there is something fundamentally wrong with my import statements or something but i am at a loss as to what it is. How do I correct this so that I can create an instance of Aclass and use its methods?
Thanks.
The problem here was that I was importing the package itself but not a module within that package. I changed my import in test.py to:
from package import package
and this fixed my issue.
Are you sure you are handling your import properly and not introducing any circular dependencies?
Also:
def __init__(file1.File1, file2.File2):
def __init__():
Your init methods are lacking self. They should be:
def __init__(self, file1.File1, file2.File2):
def __init__(self):

Some question about python's inheritance, import

I'm new to python, but skilled on java. Now I'm facing a annoying question when training on python3.5, I have such a src structure:
/project-root
--main.py
--ModelImpl.py #subclass of BaseModel
--ActionImpl.py #subclass of BaseAction
--/base
----BaseModel.py #base class of all
----BaseAction.py #subclass of BaseModel
----modulescript.py
in main.py:
from ModelImpl import ModelImpl
from ActionImpl import ActionImpl
modelImpl = ModelImpl()
actionImpl = ActionImpl()
in modulescript.py:
from BaseAction import BaseAction
baseAction = BaseAction()
in BaseModel.py:
class BaseModel:
def __init__(self):
print("BaseModel")
in BaseAction.py:
from .BaseModel import BaseModel
class BaseAction(BaseModel):
def __init__(self):
super().__init__()
print("BaseAction")
in ModelImpl.py:
from base.BaseModel import BaseModel
class ModelImpl(BaseModel):
def __init__(self):
super().__init__()
print("ModelImpl")
in ActionImpl.py:
from base.BaseAction import BaseAction
class ActionImpl(BaseAction):
def __init__(self):
super().__init__()
print("ActionImpl")
Now when I input python3 main.py in terminal, I got printed result:
BaseModel
ModelImpl
BaseModel
BaseAction
ActionImpl
but if I input python3 module function.py, I got error:
Traceback (most recent call last):
File "modulescript.py", line 1, in (module) from BaseAction import BaseAction
File "/home/jerry/projects/test/python/base/BaseAction.py", line 1, in (module) from .BaseModel import BaseModel SystemError: Parent module '' not loaded, cannot perform relative import
I found that It's cause by import statement in BaseAction.py:
from .BaseModel import BaseModel
If I change to from BaseModel import BaseModel, the modulescript.py runs ok, but the main.py will got a error:
File "main.py", line 225, in (module) from ActionImpl import ActionImpl
File "/home/jerry/projects/test/python/ActionImpl.py", line 1, in (module) from base.BaseAction import BaseAction
File "/home/jerry/projects/test/python/base/BaseAction.py", line 1, in (module) from BaseModel import BaseModel
ImportError: No module named 'BaseModel'
Oops. annoying!
In java, you can import any Class from any where if you provide the right path of the class like import com.domain.MyClass;
so, what's the right way to import in python?
This is Python, not Java, you group modules related to eachother in a single package, which is a folder.
To be able to import from a package, you must do a few things first.
Create __init__.py in your package to let interpreter know that it's a package. If there's no such file in a folder, it won't even budge whether you want to import from there or not, it's not a package to it and that's all.
Additionally, if you want (and you should when you're creating a package for others to use) import classes functions and etc in your __init__.py to allow to import them from the package itself directly.
I made a simple example:
project tree:
/root
test.py
/examplepkg
__init__.py
somemodule.py
EDIT: if you want examplepkg to have a "nested" package, as in, package it depends on in some way, you create another folder, and put another __init__.py in it and do the same thing, then in __init__.py of examplepkg you can further "export" it for the top level modules to see. How you do it is up to you, just be consistent.
somemodule.py:
class SomeClass:
def __init__(self):
print("New Instance of SomeClass!")
__init__.py:
from .somemodule import SomeClass # you could see it as exporting
test.py:
from examplepkg import SomeClass
SomeClass()
For more information, read this.
I got the same error but the error got fixed when I changed
from .BaseModel import BaseModel
to
from base.BaseModel import BaseModel

Using class from another file in python package and conflicts in __init__()

I'm writing a python package (python 3.6) and have the following directory structure:
package/
| __init__.py
| fileA.py
| fileB.py
| tests/
| | __init__.py
| | test_classA.py
| | test_classB.py
Setup
My files have the following contents:
# package/fileA.py
from package import ClassB
def ClassA:
def __init__(self):
self.my_ClassB = ClassB()
-
# package/fileB.py
def ClassB:
def __init__(self):
self.foo = "bar"
-
# package/tests/test_classB.py
from package import ClassB
# <performs some unit tests here>
-
# package/tests/test_classA.py
from package import ClassA
# <performs some unit tests here>
-
# package/__init__.py
from .fileA import ClassA
from .fileB import ClassB
Circular importing
When I ran python test_classB.py, I get the following traceback error showing that I have circular import statements, which are not allowed by python. Note - the package is not literally called package and I have edited the Traceback to match the toy example above.
Traceback (most recent call last):
File "package/tests/test_classB.py", line 2, in <module>
from package import ClassB
File "/anaconda/lib/python3.5/site-packages/package/__init__.py", line 2, in <module>
from .fileA import ClassA
File "/anaconda/lib/python3.5/site-packages/package/merparse.py", line 2, in <module>
from package import ClassB
ImportError: cannot import name 'ClassB'
Correcting the error
However, when I remove those two lines in my package/__init__.py file:
# package/__init__.py
from .fileA import ClassA
from .fileB import ClassB
...and I change the import method for package/fileA.py:
# package/fileA.py
from package.fileB import ClassB
def ClassA:
def __init__(self):
self.my_ClassB = ClassB()
... package/tests/test_classB.py runs correctly.
My Question
My question is: How can I keep the one file: one class structure in my files and import with from package import ClassA instead of having to import with from package.fileA import ClassA?
In my package I would like to import classes from other files, but don't know how to get around circular importing.
Edit: Solution
Thanks to #mirandak and #martin-kalcok below for their help.
The only file that I had to edit was fileA.py to not refer to the package name in the import statement.
# package/fileA.py
from .fileB import ClassB
def ClassA:
def __init__(self):
self.my_ClassB = ClassB()
The package/__init__.py file still contains import statements in case I want to import the package from other scripts in the future that I don't couple with the package.
# package/__init__.py
from .fileA import ClassA
from .fileB import ClassB
The problem is with package/fileA.py. It's both a part of package and calling the __init__.py file of package as it's imported - creating a circular dependency.
Can you change fileA.py to look like this?
# package/fileA.py
from .fileB import ClassB
def ClassA:
def __init__(self):
self.my_ClassB = ClassB()
First of all, renaming your package to literary "package" really confuses this whole situation, but here's my take on it :D.
I don't think you are dealing with circular dependency, python just states that it cannot import classB from package and that is because there is no file named classB in package directory. Changing import statement to
from package.fileB import ClassB
works because there is directory package which contains file fileB which contains object ClassB.
To answer your question whether you can import classes with statement
from package import ClassB
you can't, unless your package is file and classB is object inside this file. However i don't see how this different import statement would be a dealbraker
Side Note: Your objects ClassB and ClassA are not classes, they are functions. Python uses keyword class to create classes and def to define functions.
Side note 2: Are you sure your __init__.py file needs to hold any code at all?
Personal Note: I know that keeping 1 File / 1 Class structure is matter of personal preferences, it is not required in python and I myself find it much more comfortable to group multiple related classes and functions into one file

Categories