python module imports issue - python

here's a picture of my directory structure:
parts.py
machine/
__init__.py
parts.py
I have a directory (a package) called machine
in it there is __init__.py and parts.py
at the same level as machine, there is a file named parts.py
in parts.py, the code looks like this:
#parts.py
class Parts(object):
pass
in machine.parts the code looks like this
#machine.parts
from parts import Parts
class MachineParts(Parts):
pass
When I try to import machine.parts, I get an import error. I don't want to change my directory structure. How should I fix this and retain good PEP8 style?

You should make it a package by adding top-level __init__.py and giving some meaningful name to top-level directory:
mypackage
__init__.py
parts.py
machine/
__init__.py
parts.py
Then, use absolute imports:
#machine.parts
from mypackage.parts import Parts
class MachineParts(Parts):
pass

Since import supports relative imports, try:
from ..parts import Parts
Another option is to use an absolute import:
from appname.parts import Parts
As mentioned in How to import a Python class that is in a directory above?

Related

ValueError: attempted relative import beyond top-level package python

I have a directory structure like this.
Chatbot/
utils/
abc.py
projects/
proj1/
utils/
__init__.py
data_process.py
components/
class1.py
I have two utils folders in my structure, one at the top level and one inside my projects folder.
Now I want to import data_process.py file inside class1.py. So I tried like this
from utils.data_process import DataProcess
but it is referencing the top-level utils folder and even VSCode is not recognizing it. I tried creating __init__.py file inside the utils folder but still did not work.
I tried with empty __init__.py and then placing this content
from . import data_process
__all__ = ['data_proces']
then
from .data_process import DataPreprocess
__all__ = ['DataPreprocess']
then I tried
from ..utils.data_process import DataProcess
VSCode is recognizing this but it is not working and throws the error
ValueError: attempted relative import beyond top-level package
Even I tried changing the name utils to some other name but still the same issue
How can I solve this?
A python module is defined by a special file called __init__.py and this file should be present in all the subdirectories. So, your file structure would be:
Chatbot/
__init__.py
utils/
__init__.py
abc.py
projects/
__init__.py
proj1/
__init__.py
utils/
__init__.py
data_process.py
components/
__init__.py
class1.py
class2.py
Now, you can do a relative import like:
Use . for importing something within the same directory. Example:
# file Chatbot/projects/proj1/components/class2.py
from .class1 import *
Similarly, use .. for two-level, and ... for three-level, and so on!
For instance:
# file Chatbot/projects/proj1/components/class2.py
from ..utils.data_process import * # import from data_process.py
# there will be four "." earlier I made a counting mistake
from ....utils.abc import * # import something from abc.py
Coding Convention
When writing a python module/package, you might want to follow PEP8 Convention.
Moreover, I believe you are trying to do different projects using your package Chatbot, is that correct? Then, it is a good practice that you set PYTHONPATH for Chatbot and do all the projects, and imports seperately.
EDIT: Uploading Dummy File
I'm able to work on this project seamlessly even with using two utils directories. Project Structure:
main file and its output:
# file main.py
from chatbot.utils.abc import hello as a1
from chatbot.projects.proj1.components.class1 import super_hello
from chatbot.projects.proj1.utils.data_process import hello as b1
print(a1(), b1())
print(super_hello())
Similarly, if you have chatbot under PYTHONPATH you can call the project from anywhere from your device.
Code details and files are added into my github account for details.
sys.path is where Python searches to find modules and packages and It does it in order.
So you can put ...../proj1/ at the beginning of the list, when python start searching it will find the utils folder in that path first !
import sys
sys.path.insert(0, r'...../proj1/')
But this cause another problem, python always find utils in that folder first, that's not what you want.
solution number 1
Absolute import:
from Chatbot.projects.proj1.utils.data_process import DataProcess
solution number 2
use relative imports which is mentioned by #Mr.Hobo.

"No module named MyClass" error on PyCharm

I am using PyCharm Community Edition 2016.3.1 but when I have two+ python files on the same directory, if I import one of them into the other it gets underlined saying:
# main.py
import MyClass1
No module named MyClass1 less... (Ctrl+F1) This inspection detects names that should resolve but don't. Due to dynamic dispatch and duck typing, this is possible in a limited but useful number of cases. Top-level items are supported better than instance items.
but when I execute my main.py it works properly.
Other regular imports like import sys don't get underlined.
If those two python files are under the same directory eg. MyDirectory, you need to import the classes using the MyDirectory as the root. So for example if you have the below project structure:
└── MyDirectory
├── file1.py (MyClass1)
└── file2.py (MyClass2)
To import the MyClass1 into the file2.py you can do it as below:
from MyDirectory.file1 import MyClass1
The reason you are getting this error is because you are not importing correctly.
Python imports follow this syntax.
import filename
This means you need to have a file name filename.py in the current directory. You can also import a specific class from that file like so.
from filename import MyCalss

How to import a class defined inside __init__.py in same package?

I have a package like
package/
--__init__.py
--test.py
Lets assume class Sample defined inside __init__.py then how can I import the class Sample from test.py.
Using a relative import, . is package's root:
from . import Sample
Also, it is bad practice to include "real" code/logic in __init__.py. Most of the time, you should only import stuff within __init__.py, to make it externally importable from package level.
Things defined in __init__.py become part of the package's namespace:
test.py:
import package
print(package.Sample)

Import package from unit test code

I like to keep my source code separate from test code. So, I have my project organized like this:
my_package/
module1.py
module2.py
tests/
units/
test_a.py
test_b.py
perf_tests.py
How should test_a.py import my_package?
Note: I've googled this (including SO) and am not satisfied with the answers:
I don't want to use setup.py, because I want to run from development; this is for testing, after all
I don't want to use symlinks or other hacks
I've tried sys.path.append('../') and sys.path.append(os.path.realpath('../')). Both result in ImportError: No module named my_package. Perhaps something similar can be done with PYTHONPATH - What is the syntax?
I do want to write a proper import statement which can find the correct files
First you have to include a __init__.py file inside folder my_package in order to allow Python to recognize this folder as a valid module. You can create an empty __init__.py file just with one line pass, for example.
Then, you can do something like this in test_a.py:
import os
bkp = os.getcwd()
os.chdir(r'..\..')
import my_package
os.chdir(bkp)
Or use the other options with PYTHONPATH or sys.path.append().

Python packages - import by class, not file

Say I have the following file structure:
app/
app.py
controllers/
__init__.py
project.py
plugin.py
If app/controllers/project.py defines a class Project, app.py would import it like this:
from app.controllers.project import Project
I'd like to just be able to do:
from app.controllers import Project
How would this be done?
You need to put
from project import Project
in controllers/__init__.py.
Note that when Absolute imports become the default (Python 2.7?), you will want to add a dot before the module name (to avoid collisions with a top-level model named project), i.e.,
from .project import Project

Categories

Resources