How to call a module from a previous parent directory? - python-3.x

I am running a Flask application at PythonAnywhere. I'm using Python 3.8. The folder structure looks like this:
project/
app.py
alpha/
beta/
gamma/
other.py
All of the folders have a blank __init__.py. From inside other.py, I want to do an import like:
from project.app import function
What is the cleanest way to make this happen?
I've seen suggestions to use import importlib.util in other answers. Will that work in PythonAnywhere? Instead of doing that in other.py is there a way to do this once and it work for the whole project? (so that things like from project.alpha.beta import function would work as well)

I have a partial answer. Partial because I'm not sure it is the best answer. In the PythonAnywhere web configuration the working directory is listed as /home/username/mysite/project. As per the example above, project had a module I was trying to reference. So at the top of app.py (in the project folder), I added this:
import sys
sys.path.append("/home/username/mysite")
Basically I added the directory above the module directory to the import path. That got me through the error, but it doesn't seem like the best solution.
I do want to give a shoutout to this PythonAnywhere help page because it has some good module debugging tips.

Related

importing a function defined in a different directory

Disclaimer: I am studying Python. I am given a task of reusing functions.
the function is simple:
app/utils/calculators.py
def calculate_session(session_type, session_code):
return 3 # just to save space
Now i need to use the function from a different file but for the life of me, I failed to import it. I have already added init.py to utils directory, to the app directory as well.
app/tasks/process_sessions.py
from utils.calculators import calculate_session
but when I run it, it fails saying module not found. I am in a virtual environment and all the files go in app directory.
What am I missing?
You'll want to specify the full path of the file (including the root directory) and import the specific function. Example below:
from app.utils.calculators import calculate_session
This should then import your function, regardless of whether you're using a virtual environment.

The file is in the same directory but cannot be imported

The python version I am using is 3.8.2
I searched a lot and most of the solutions are to use sys.path.append()
But it didn't solve the problem for me, if I use from . import players
it will say
ImportError: attempted relative import with no known parent package
if i use import players it will say
ModuleNotFoundError: No module named 'players'
The code I used to fix this:
sys.path.append(".")
sys.path.append(os.getcwd() + "\\players.py")
sys.path.append(os.getcwd())
still can't fix this,It's worth mentioning that at some point sys.path.append(os.getcwd() + "\\players.py") can run
Make sure that the name of the file is actually players.py.
And not for example players.py, players .py (note the spaces).
Also check for all other "invisible" Unicode characters that would not necessarily show up.
And make sure that there is no directory players as well.
I deleted the file completely so I couldn't test it, but I ran into this problem again, it's an import order problem, I tried to import attributes.py first and then content.py, there was a problem Check, can't find attributes.py , the problem is solved when their import order is swapped, I can't understand why, but if you encounter such problems please try once (other files are not imported)
I've had similar issues and I've created a new, experimental import library for Python to solve this kind of import error: ultraimport
Instead of from . import players it allows you to write
import ultraimport
players = ultraimport('__dir__/players.py')
This will always work, no matter how you run your code, no matter what is your current working directory and no matter if there's another directory somewhere called 'players'.

How can I set up an alias for imports in Python?

I want my project to work in two different situations. It should work as a standalone library, but also as sub package of a larger project. The main use case is that of a standalone library, where its internal imports should be of the form
from my_library import sub_package
When using the code as sub package of a larger project, these imports don't work as there is no global name my_library. Instead, I would have to use relative or absolute imports, for example
from large_project.my_library import sub_package
Let's assume I wrote my library as shown in the first example. How can I overwrite importing behavior when running as part of a larger project to automatically adjust import paths?
Thanks to #MatrixTai's suggestion of adding the parent directory of the package to the the module path, I came up with this dynamic solution. At the top of my_library/__init__.py:
# Make package global even if used as a sub package to enable short imports.
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
We have to navigate up two directories here to do from the my_library/__init__.py to my_library and from there to its parent direction, where imports will find the library.
You don't have much choice.
If you want to reference the my_library.py anywhere, there is 2 method (as I known) can do similar work.
1: add system path. Like those module you installed by pip. pip module is installed in /Python/Scripts. You can add a new path or simply put my_library.py into one of the path. For adding, that's in Computer(right-click)-> Properties -> Environment Variable -> Choose Path and Click Edit
(Though you may not want to use this.)
2: Changing __init__.py, but still at least one line you must add in my_library.py.
For example,
/Directory
/large_project
-__init__.py #call this sub_init
-my_library.py
-__init__.py #call this main_init, this fake
-main.py
In main_init,
import sys
sys.path.append('\\Directory\\large_project')
As main_init is not executed when you execute main.py (this is fake), so in main.py
import __init__
from my_library import sub_package
But as well you can take this main_init as the starter of library, like declaring __all__, etc.

Python import scheme

I am trying to write a python library, where some files depend on other files, for example:
I have folder structure:
../libname
../libname/core.py
../libname/supplementary1.py
../libname/supplementary2.py
../libname/__init__.py
where libname is where I import from.
the core.py file begins with:
import supplementary1
import supplementary2
...some code...
and this works fine, if I test it in the main of the core.py
Let's say I want to use libname as library in my project. My folder structure is then:
./libname
./main.py
where main.py calls functions from core.py, which in fact need functions from supplementary1 and supplementary2.
Currently, it throws me an error, saying there is no supplementary1, if I try (in main.py)
from core.py import function1
My question is, how do I import files from my library then? I mean one option would be to copy all the code from e.g. supplementary1 to the core.py, but I wish to maintain my code elegantly separated, if possible.
So in other words, how does one import a file, which already imports some files from a local library?
Thank you very much.
In import ... and from ... import ... you need to write not the filename, but module name. Instead of core.py you should say libname.core, meaning "module core, from package libname" (libname will be searched in all module paths, that normally includes the directory of the script you've started, i.e. where your main.py is).
tl;dr: a simple answer to your question is to write from libname.core import function1 instead.
Also, I'd suggest to use relative imports and instead of import supplementary1 write from . import supplementary1 - here, from . means "from the current package - where this file (module) resides in".
Consider reading Python documentation on modules - there are a lot of examples and explanations there.

How to structure my little python framework

I wrote a simple set of python3 files for emulating a small set of mongodb features on a 32 bit platform. I fired up PyCharm and put together a directory that looked like:
minu/
client.py
database.py
collection.py
test_client.py
test_database.py
test_client.py
My imports are simple. For example, client.py has the following at the top:
from collection import Collection
Basically, client has a Client class, collection has a Collection class, and database has a Database class. Not too tough.
As long as I cd into the minu directory, I can fire up a python3 interpreter and do things like:
>>> from client import Client
>>> c = Client(pathstring='something')
And everything just works. I can run the test_files as well, which use the same sorts of imports.
I'd like to modularize this, so I can use it another project by just dropping the minu directory alongside my application's .py files and just have everything work. When I do this though, and am running python3 from another directory, the local imports don't work. I placed an empty init.py in the minu directory. That made it so I could import minu. But the others broke. I tried using things like from .collection import Collection (added the dot), but then I can't run things in the original directory anymore, like I could before. What is the simple/right way to do this?
I have looked around a bit with Dr. Google, but none of the examples really clarify it well, feel free to point out the one I missed
In this file ...minu/__init__.py import the submodules you wish to expose externally.
If the __init__.py file contains the following lines, and the client.py file has a variable foo.
import client
import collection
import database
Then from above the minu directory, the following will work:
from minu.client import foo

Resources