Why won't my class import in Python? - python

Edit: __init__.py files are included, but I'm using Python 3 - I don't think it matters.
Another edit: Anything in config.py will import with no problem. If I simply omit from cache import Cache then no errors. Interestingly, no errors occur when importing Config in config.py
I cannot figure out what's wrong here. I'm getting an error whenever I try to import a specific class. Here's what my project layout looks like:
app/
dir1/
config.py
cache.py
manager.py
__init__.py
test/
test.py
__init__.py
cache.py:
import sys
import os
sys.path.append(os.path.dirname(__file__))
from manager import Manager, AnotherClass
from config import Config
manager.py
import sys
import os
sys.path.append(os.path.dirname(__file__))
from config import Config
from cache import Cache
test.py
cwd = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.abspath(os.path.join(cwd, os.pardir)) + '/dir1')
from cache import Cache, AnotherClass
from manager import Manager
test = Cache()
...
So when I run test.py I get this:
File "/path/to/project/app/dir1/<module>
from cache import Cache
ImportError: cannot import name 'Cache'
from manager import Manager line 5,
Even though config.Config loads just fine, no errors there, but as soon as I try to import cache.Cache it suddenly can't find or import any class in cache.py. All files have the same permissions. Can someone tell me what's wrong here?

You are missing the __init__.py file in your module
app/
__init__.py
dir1/
__init__.py
config.py
cache.py
manager.py
test/
test.py
and instead of messing with sys.path should do a relative import like
from .config import Config
from .cache import Cache
Python 2 may also need a line
from __future__ import absolute_import
before those imports.

Related

import package dynamically

I'd like to understand if there's better solution .
for following tree:
|-main.py
├── app_config
│   ├── db_config.py
| |--- settings.py
Main.py importing class from db_config
from app_config.db_config import DBContext
So in db_config.py each import of other class would be in the context/position of main
meaning
from app_config.settings import SingletonMeta
This obviously works but during development sometimes need to test db_config.py itself
and each time need to change import of settings.py
from settings import SingletonMeta
I wonder if there's more efficient way
You can add the following code in your db_config.py script:
import sys
from pathlib import Path
sys.path.append(str(Path(__file__).parent.parent))
from app_config.settings import <package>
This way, you add the parent directory of db_config.py to sys and this will alows you to import packages inside your script as from app_config.settings import <any package under app_config > and also in main.py

attempted relative import with no known parent package (python)

I'm trying to import the db module from the __init__ file, after comand from . import db, gets attempted relative import with no known parent package
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
My catalog structure:
Procjet
├── __init__.py
├── auth.py
└── templates
i tried it:
from . import db
from .. import db
from project import db
from .project import db
and always i gets attempted relative import with no known parent package
Opening the project folder directly in an IDE should fix the issue.
You could check if the correct path is in sys.path in debug mode for example.
You could try my new import library: ultraimport
It gives the programmer more control over their imports and lets you do file system based relative and absolute imports.
To import the db object relatively, your auth.py could look like this:
import ultraimport
db = ultraimport('__dir__/__init__.py', 'db')
This will always work, no matter how you run your program and independent of your sys.path.

I need help importing modules into tests from sibling folder

I get an import error "unable to import module" when I try to import a module
File structure
src
modules
__init__.py
authenticate_developer
twttier_importer
notebooks
main.ipynb
unit_tests
test_authenticate_developer
In test_authenticate_developer
import requests
from nose.tools import assert_true
import os
import sys
sys.path.append(os.path.abspath('../modules'))
import settings
import twitter_importer #returns import error
import authenticate_developer #returns import error
However when I use the same syntax in my notebooks it is successful.
import sys
import os
sys.path.append(os.path.abspath('../modules'))
sys.path.append(os.path.abspath('../'))
import twitter_importer
import authenticate_developer
import settings
I have looked at existing answers and I tried them out i.e., removing init.py from the root folder and removing or adding init.py to the tests folder. None seems to work for me.
I managed to get someone to help me with these and this is how we tackled it.
src
modules
__init__.py
authenticate_developer
twttier_importer
notebooks
main.ipynb
unit_tests
__init__.py
test_authenticate_developer
In test_authenticate_developer
import os,sys,inspect
sys.path.append(os.path.abspath('../modules'))
#This is to access the parent folder in order to import config
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0,parentdir)
import config
from modules.authenticate_developer import Authenticate
I cannot explain why I have to do it differently in the test files but this is my work around

Python can't import module from package

I have a flask restful project with the following layout (file names changed for convenience)
myproject/
__init__.py
app.py
common/
__init__.py
util.py
foo/
__init__.py
main.py
utilities.py
foo/ is just a folder containing code for one of the API endpoints, I'm planning to add others in the future, for this reason I have common/util.py file which contains reusable functions that I will use with other API endpoints.
foo/main.py
from flask_restful import Resource, request
from utilities import Analysis
class Foo(Resource):
def get(self):
pass
in foo/utilities.py I have classes with methods that get some data, I import those classes to foo/main.py to return JSON response
classes in foo/utilities.py also uses some functions from common/util.py but when I try to import something from common/util.py to foo/utilities.py I get import common.util
ModuleNotFoundError: No module named 'common'
What could be causing this? I tried importing various ways:
from common.util import my_func
from .common.util import my_func
from myproject.common.util import my_func
but none worked.
This is myproject/app.py in case it matters:
from flask import Flask
from flask_restful import Api
from foo.main import Foo
app = Flask(__name__)
api = Api(app)
api.add_resource(Foo, '/Foo')
if __name__ == "__main__":
app.run()
I'm doing all of this in activated virtualenv if it matters
from common.util import my_func
In Python 3 this is an absolute import, that is, the directory with common/ subdirectory must be in sys.path. In your situation it's certainly a wrong approach.
from .common.util import my_func
This import expects common to be a subdirectory of foo which is also not the case.
from myproject.common.util import my_func
This is finally the best approach but for it to work the parent directory of myproject/ subdirectory must be in sys.path. Either you install the entire myproject or add the parent directory to $PYTHONPATH environment variable or add the directory to sys.path in foo/main.py. Something like:
PYTHONPATH=/home/to/parentdir /home/to/parentdir/myproject/foo/main.py
or
import sys
sys.path.insert(0, '/home/to/parentdir')
/home/to/parentdir is the directory where myproject/ is.
After installing myproject or adding its parent directory to sys.path you can also use relative import. You need to remember that common is a sibling package comparing to foo so the import must be not from .common but from ..common:
from ..common.util import my_func

Relative import in Python 3.6

I want to use relative import in Python 3.
My project:
main_folder
- __init__.py
- run.py
- tools.py
I want to have in run.py (MyClass declared in __init__.py):
from . import MyClass
And in run.py:
from .tools import my_func
An ImportError is raise.
Alternatively, with absolute import, debugging in PyCharm does not work and the library takes from installed packages, not my directory.
I know one way, but it is terrible:
sys.path.append(os.path.dirname(os.path.realpath(__file__)))
How to use this import in my project?
When you use PyCharm, it automatically makes the current module main, so relative statements like from . import <module> will not work. read more here.
to fix your problem, put the __init__.py and tools.py files in a sub-directory
main_directory/
run.py
sub_directory/
__init__.py
tools.py
in your run.py file, write the following as your import statements
from sub_directory import tools
from sub_directory.__init__ import MyClass
Edit: as #9000 mentioned, you can write from sub_directory import MyClass and achieve the same thing.

Categories