Python Importing package at same level but different directory - python

python version:3.9.6
I cannot seem to get this to work I know there are a million posts that are the same as this but the solutions never seem to work for me. I've run into this before and always end up just restructuring the folders to include all files in one path which is obviously not ideal. So here I am once again asking you guys for help.
My folder structure is as follows
|project
|my_service
-my_service.py
|tests
- tests.py
I'm trying to get the function get_num_back from my_service.py and import it into tests.py.
I've tried relative imports from ..my_service.my_service import get_num_back this doesn't work because from what I've read I cannot hit the root folder.
I've then tried absolute import from my_service.my_service import get_num_back which is the answer I see works for everyone else but it doesn't seem to work for me. I've then tried from project import my_service as well as from project.my_service import my_service. as far as I understand with my python version I do not need __init__.py but I've also tried it with that as well.
the error
ModuleNotFoundError: No module named 'project'
Please settle this for me once and for all!

Always run py.test from your project directory.
Because from that directory it can actually find my_service.
For more information, read up on relative imports in the language reference documentation.

Related

Python: After separating out modules to their own package, local imports failing

I have a project which worked perfectly fine, but I wanted to separate some of the code into a separate project (with its own packages). I have successfully done that, but now in that newly separated package I need to explicitly import local modules using from . import <module> instead of import <module> - the latter of which had worked before separating the modules into their own package.
The new imports (where I include the dot representing the local dir) works but it seems like it should also just work without having to specify the module locations since the files are in the same directory as the module that is trying to import them. Am I missing something here?
Artificial example:
|-root
|--ProjectA
|---app.py
|-root
|--ProjectB
|---ProjectB
|----__init__.py
|----libA.py
|----libB.py
In app.py I am able to import a module from ProjectB (I have adjusted PYTHONPATH to include /root/ProjectB). So the following works just fine as I would expect:
from ProjectB import libA.py
But the entire thing fails because in libA.py the following does not work:
import libB
Instead I have to use:
from . import libB
I have tried to wrap my head around how python imports work across packages and I thought I had sorted it in my head, but apparently I am missing something. Unless this is the way it is supposed to work? (packages need to explicitly indicate that a module is local). But I thought python would always implicitly add the path of the current module that is doing the importing.
Any advice (or even just links to tutorials that explain this - I have watched a lot but they all tend to focus on different aspects of importing than this) is greatly appreciated.

Importing self-made package

I am testing my own package, but I am struggling to import it. My package file structure is as follows:
(You can also alternatively view my Github repository here)
In PyAdventures is my init.py with the content of
name="pyadventures"
So my question is, when I import it in another python file, how come it doesn't work?
I run:
import pyadventures
But I get the following error:
No module named pyadventures
It'd be great if you could answer my question!
It's important to note that the package is in my Python package directory, not the test one I showed
New discovery! In my PyAdventures folder (the one Python actually uses) the folder only has a few files, not the ones in the screenshot above.
You can install this with pip install pyadventures
Ah, like others remark in comments and answer: The camelcase might be the problem. (Why not name it just all in lower case: pyadventures? - Else users will be as confused as its developer now :D .)
Before, I thought, it might be a problem that you want to use your module without having installed it (locally). And my following answer is for this case (using a not installed package from a local folder):
In the docs you can read:
The variable sys.path is a list of strings that determines the
interpreter’s search path for modules. It is initialized to a default
path taken from the environment variable PYTHONPATH, or from a
built-in default if PYTHONPATH is not set. You can modify it using
standard list operations:
import sys
sys.path.append('/ufs/guido/lib/python')
thus, before import do:
import sys
sys.path.append('/absolute/or/relative/path/to/your/module/pyadventures')
# Now, your module is "visible" for the module loader
import pyadventures
Alternatively, you could just place your pyadventures module folder locally in your working directory where you start python and then just do
import pyadventures
However, it is much easier to manage to keep only one version in one place and refer to this from other places/scripts. (Else you have multiple copies, and have difficulties to track changes on the multiple copies).
As far as I know, your __init__.py doesn't need to contain anything. It works if it is empty. It is there just to mark your directory as a module.
Simple. Even though the package listed on pip is namd pyadventures, in your code the directory is called PyAdventures. So that's what python knows it as. I ran import PyAdventures and it worked fine.

Cannot import module from another module, but can so from a third module (all in different packages)

my setup:
project
extract (package)
-> extract_step.py
text (package)
-> paragraph.py
util (package)
-> paths.py
All three packages have empty __init__.py in them. PyDev also shows the packages with the package icon if that matters.
In extract_step.py I can import like so:
from text.paragraph import Paragraph
And instantiate Paragraph objects and use them.
In paths.py I try to import the exact same way, but I get:
ImportError: No module named 'text.paragraph'; 'text' is not a package
I am using Eclipse and PyDev 5.3. Python 3.5.2.
My PYTHONPATH in Eclipse has only:
/${PROJECT_DIR_NAME}
I can run the extract_step.py without issues, but I can not run paths.py without getting the error message (even if the import is the only line in paths.py). What can I do to fix this and why does this happen?
EDIT:
I have tried making a new package, with a new module test.py. I can import in that! I have also tried making a new module in the util package, and it does not work in that either.
Solution (to fix it):
I deleted the util package.
I re-created the package and the paths.py.
It now works.
This answers the "How do I fix this" part of my question, but not the WHY.
If anyone knows why this happened I will accept their answer, but for now, if anyone runs into the same problem, this is how I fixed it.

Python program structure importError

I have this structure of a python project:
RF
\__init__.py
----tools
--------\__init__.py
--------drawtools.py
----examples
--------\__init__.py
--------something.py
All __init__.py are left blank. Now, in "something.py" I type:
from RF.tools.drawtools import *
And I get:
ImportError: No module named RF.tools.drawtools
What's the correct program structure? Do I have to put something in the init files?
I notice that if "something.py" is in the top directory it works. The strange thing is that PyCharm, the IDE I'm using, seems to recognize the import and give me code completion.
I heard something about setting PYTHONPATH but as this project must be shared in a team I'd prefer to keep things as simple as possible (you copy the project from one to one and run it without any annoying importError).
I think that it would work with a relative import, such as
from .. import drawtools

py2exe cannot import Module from other directory

I am bundling python source code with py2exe. The directory structure is as follows:
some_Mod.py
some_dir/another_dir/some_Mod.py
Inside the latter some_dir/another_dir/some_Mod.py I am trying to import the other Python Module with
from ..some_Mod import *
Using the import causes no problems with the python interpreter, but if I run the same constellation in the bundled package, I get an Exception:
ImportError: No module named some_Mod
Can somebody explain why?
Remark: Renaming the Modules is actually no problem, but I was just wondering, why py2exe cannot deal with this constellation.
If you have __init__.py files in each of those sub-directories then all import statements should work correctly.
Assuming that's not the problem, here's an excellent guide to importing best practices:
http://blog.habnab.it/blog/2013/07/21/python-packages-and-you/
In summary, never use relative imports - always absolute (see the link above for why).
Second (and I'm not entirely sure why), always keep your py2exe setup.py script in the exact folder where your main script is. I've tried modifying py2exe's 'script' option to allow my script to be somewhere else... but your exact problem happened to me. So, try making sure it is right where the main script is.
Finally, you can always give py2exe a little help. I usually have to add the root directory to the system path so the import statements are valid. Note, I'm not modifying sys.path in any of my application's code - only the py2exe script I use to build the exe.
At the top of my py2exe setup script:
import sys
sys.path.append(PATH_WHERE_PACKAGES_ARE)
# add any packages that need explicit importing here located in root directory:
import package1 # apparently it wasn't found...
import package2 # apparently same thing
Generally I don't import packages though, adding the project root where they exist usually is enough.
I'm not sure that py2exe now how to handle the from ..some_Mod import * syntax, check this to ensure that the some_Mod.py module is correctly packaged : python -m py2exe.mf -d some_dir/another_dir/some_Mod.py as explained in the py2exe FAQ

Categories

Resources