How do I import from a great-great-grandparent directory in Python? - python-3.x

I feel a little embarrassed for not knowing this already but it's something I've always struggled with. I have a directory like this:
marketing-reports/
utils.py
Reporting/
Adhoc/
for_sales/
salesperson1/
current.py
I want to import utils.py from current.py but every suggestion I have seen so far does not work.
I have seen two main suggestions. The first involves using sys.path. I have tried that as below:
import sys
sys.path.insert(1, 'C:\\marketing-reports\\Reporting')
from Reporting import utils
... result is:
Exception has occurred: ModuleNotFoundError
No module named 'Reporting'
I have also tried another suggestion I got from this article like
import path
import sys
# directory reach
directory = path.path(__file__).abspath()
# setting path
sys.path.append(directory.parent.parent)
# importing
from Reporting import utils
... but this solution is kind of a non-starter since VSCode tells me "Import "path" could not be resolved by Pylance". I tried to fix this by running py -m pip install path, but that still didn't fix anything because I got Exception has occurred: AttributeError: module 'path' has no attribute 'path'. Then I changed path to Path which VSCode seemed to like better, but after all that I got right back to where I started with the No Module named 'Reporting' error.
What's going on here? What's the best way to import this? I feel like I'm making this a lot harder than I need to.

According to your directory tree, utils is not located inside Reporting.
First solution fixed:
import sys
sys.path.insert(1, 'C:\\marketing-reports')
import utils
Optional solution, depending on your way of running the code:
from ..... import utils
I do believe you might need to repackage utils.py somewhere else, but for simple uses these solutions will work.

Related

Why do my import statements give error in VS code while working in PyCharme?

I'm writing an Assembler in Python and I'm trying to switch to VS code for my development task since I enjoy really much its simplicity. After loosing an afternoon trying to figure out why my import statements give error, I tried to open the same project in PyCharm and everything went fine.
The structure of my project:
/assembler
/src
__init__.py
code.py
main.py
parser.py
symbol_table.py
So I ended up losing a lot of time on Python 3.6 documentation to figure out what I was doing wrong, and then after discovering that the code was ok I just couldn't find anything to determine what in my configuration caused the issue, not even on VSCode issues questions.
This is my simple main() function that should import the classes within the other modules in the same package.
from src.parser import Parser
from src.code import Code
from src.symbol_table import SymbolTable
def main():
parser = Parser()
code = Code()
symbol_table = SymbolTable()
parser.has_more_commands()
main()
It should just print something on the screen to acknowledge that the import went fine, instead i get this error:
Traceback (most recent call last):
File "c:/Users/miche/Desktop/NAND2TETRIS/projects/06/assembler/src/main.py", line 1, in
from src.parser import Parser
ModuleNotFoundError: No module named 'src'
Has anyone had my same issue with VSCode and could tell me what's wrong with my configuration or statements?
I don know exactly the problem in Windows VS Code but maybe the relative path is wrong. I had an similar problem on macOS.
In /assembler/src/__init__.py try:
from .parser import Parser
from .code import Code
from .symbol_table import SymbolTable
and in your main.py try:
from .src import Parser, Code, SymbolTable

Importing submodules

I am new to python and i m having a really bad time to overcome a problem with the importing system.
Lets say i have the file system presented below:
/src
/src/main.py
/src/submodules/
/src/submodules/submodule.py
/src/submodules/subsubmodules
/src/submodules/subsubmodules/subsubmodule.py
All the folders (src, submodules, subsubmodules) have and empty __init__.py file.
In submodule.py i have:
from subsubmodules import subsubmodule
In main.py i have:
from submodules import submodule
When i run submodule.py python accepts the import. But when i run main.py python raises error for the import of subsubmodule.py because /src/submodules/subsubmodules/ folder is not in the path.
Only solution is to change the import of submodule.py to
from submodules.subsubmodules import subsubmodule
This seems to me as an awful solution because after that i cannot run submodule.py and i m sure that something else is the key to that.
An other solution is to add the following code to the __init__.py file:
import os
import sys
import inspect
cmd_subfolder = os.path.split(inspect.getfile(inspect.currentframe()))[0]
if cmd_subfolder not in sys.path:
sys.path.insert(0, cmd_subfolder)
Is there any way to do this using just the importing system of python and not other methods that do it manually using, for example sys.path or other modules like os, inspect etc..?
How can i import modules without caring about the modules they import?
You can run subsubmodule.py as
python3 -m submodule.subsubmodules.subsubmodule
If you want a shorter way to invoke it, you're free to add a shell or Python script for that on the top level of your package.
This is how imports work in Python 3; there are reasons for that.
You can avoid this issue by using sys.path in your program.
sys.path.insert(0, './lib')
import subsubmodule
For this code, you can put all your imports to a lib folder.
You can read the official documentation on Python packages where this is explained in depth.

AttributeError when packaging python library

I'm in the process of learning how to package a python library using the official guide. I've started cloning the minimal sample package suggested in the guide here. I've then added the file my_module.py inside the folder sampleproject storing a simple power function. Another function is also stored in /sampleproject/sampleproject/__init__.py. The resulting structure of the library is the following
Finally, I've used pip to successfully install the package in the interpreter. The only thing left is to make sure that I'm able to run the functions stored in the subfolder sampleproject.
import sampleproject
sampleproject.main()
# Output
"Call your main application code here"
This is great. The package is able to run the function in __init__.py. However, the package is not able to find module.py:
import sampleproject
sampleproject.module
# Output
AttributeError: module 'sampleproject' has no attribute 'module'
I've tried to add __init__.py in the main folder and to change the settings in entry_points in setup.py without success. What should I let sampleproject to be able to find the function in module.py?
Your sampleproject.module is a function you would like to execute?
In this case, do as for the sampleproject, add () to execute it:
sampleproject.module()
Otherwise, you can import your package like this:
import sampleproject.module
or:
from sampleproject import module
To be clearer, you would have to import module in your sampleproject __init__.py. Then, when you want to use the package, import it (is some py file at root):
import sampleproject # is enough as it's going to import everything you stated in __init__.py
After that, you can start to use what's in the package you imported with maybe module() if you have a function called module in your package.
init.py discussions
it seems,
you are in sampleproject->module.py
so you need to try,
from sampleproject import module

ModuleNotFoundError: No module named '__main__.xxxx'; '__main__' is not a package

Currently trying to work in Python3 and use absolute imports to import one module into another but I get the error ModuleNotFoundError: No module named '__main__.moduleB'; '__main__' is not a package. Consider this project structure:
proj
__init__.py3 (empty)
moduleA.py3
moduleB.py3
moduleA.py3
from .moduleB import ModuleB
ModuleB.hello()
moduleB.py3
class ModuleB:
def hello():
print("hello world")
Then running python3 moduleA.py3 gives the error. What needs to be changed here?
.moduleB is a relative import. Relative only works when the parent module is imported or loaded first. That means you need to have proj imported somewhere in your current runtime environment. When you are are using command python3 moduleA.py3, it is getting no chance to import parent module. You can:
from proj.moduleB import moduleB OR
You can create another script, let's say run.py, to invoke from proj import moduleA
Good luck with your journey to the awesome land of Python.
Foreword
I'm developing a project which in fact is a Python package that can be installed through pip, but it also exposes a command line interface. I don't have problems running my project after installing it with pip install ., but hey, who does this every time after changing something in one of the project files? I needed to run the whole thing through simple python mypackage/main.py.
/my-project
- README.md
- setup.py
/mypackage
- __init__.py
- main.py
- common.py
The different faces of the same problem
I tried importing a few functions in main.py from my common.py module. I tried different configurations that gave different errors, and I want to share with you with my observations and leave a quick note for future me as well.
Relative import
The first what I tried was a relative import:
from .common import my_func
I ran my application with simple: python mypackage/main.py. Unfortunately this gave the following error:
ModuleNotFoundError: No module named '__main__.common'; '__main__' is not a package
The cause of this problem is that the main.py was executed directly by python command, thus becoming the main module named __main__. If we connect this information with the relative import we used, we get what we have in the error message: __main__.common. This is explained in the Python documentation:
Note that relative imports are based on the name of the current module. Since the name of the main module is always __main__, modules intended for use as the main module of a Python application must always use absolute imports.
When I installed my package with pip install . and then ran it, it worked perfectly fine. I was also able to import mypackage.main module in a Python console. So it looks like there's a problem only with running it directly.
Absolute import
Let's follow the advise from the documentation and change the import statement to something different:
from common import my_func
If we now try to run this as before: python mypackage/main.py, then it works as expected! But, there's a caveat when you, like me, develop something that need to work as a standalone command line tool after installing it with pip. I installed my package with pip install . and then tried to run it...
ModuleNotFoundError: No module named 'common'
What's worse, when I opened a Python console, and tried to import the main module manually (import mypackage.main), then I got the same error as above. The reason for that is simple: common is no longer a relative import, so Python tries to find it in installed packages. We don't have such package, that's why it fails.
The solution with an absolute import works well only when you create a typical Python app that is executed with a python command.
Import with a package name
There is also a third possibility to import the common module:
from mypackage.common import my_func
This is not very different from the relative import approach, as long as we do it from the context of mypackage. And again, trying to run this with python mypackage/main.py ends similar:
ModuleNotFoundError: No module named 'mypackage'
How irritating that could be, the interpreter is right, you don't have such package installed.
The solution
For simple Python apps
Just use absolute imports (without the dot), and everything will be fine.
For installable Python apps in development
Use relative imports, or imports with a package name on the beginning, because you need them like this when your app is installed. When it comes to running such module in development, Python can be executed with the -m option:
-m mod : run library module as a script (terminates option list)
So instead of python mypackage/main.py, do it like this: python -m mypackage.main.
In addition to md-sabuj-sarker's answer, there is a really good example in the Python modules documentation.
This is what the docs say about intra-package-references:
Note that relative imports are based on the name of the current module. Since the name of the main module is always "__main__", modules intended for use as the main module of a Python application must always use absolute imports.
If you run python3 moduleA.py3, moduleA is used as the main module, so using the absolute import looks like the right thing to do.
However, beware that this absolute import (from package.module import something) fails if, for some reason, the package contains a module file with the same name as the package (at least, on my Python 3.7). So, for example, it would fail if you have (using the OP's example):
proj/
__init__.py (empty)
proj.py (same name as package)
moduleA.py
moduleB.py
in which case you would get:
ModuleNotFoundError: No module named 'proj.moduleB'; 'proj' is not a package
Alternatively, you could remove the . in from .moduleB import, as suggested here and here, which seems to work, although my PyCharm (2018.2.4) marks this as an "Unresolved reference" and fails to autocomplete.
Maybe you can do this before importing the moduleļ¼š
moduleA.py3
import os
import sys
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from moduleB import ModuleB
ModuleB.hello()
Add the current directory to the environment directory
Just rename the file from where you run the app to main.py:
from app import app
if __name__ == '__main__':
app.run()
import os
import sys
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
will solve the issue of import path issue.

python3 ImportError: cannot import name

I work in Ubuntu16.04 x64 use python3.5 IDEA
but I got a strange question as in picture,I try rename connect,but it can't work.
How should I solve this problem? Please tell me if you known,thinks.
Try the following:
from .tpymysql import connect
I think there is something likeclass Connect() in your connect.py.
If the script to be executed is under the same path to connect.py
from connect import Connect
Else
from tpymysql.connect import Connect
The Pythonic way is making everything clear and specific. So when you want to import something, import what's inside other than the file itself.
Python3 usually throws this ImportError for relative imports. Seems relative imports are not necessary.
Try:
import tpymysql

Resources