I wrote my own module (i.e. my_module.py). This is accessing a database located in the same directory by just opening it with the path 'database.db'. But when I am using my module, the 'database.db' references the directory im using my module in.
For example I have following directory structur:
/main
/my_module
my_module.py
database.db
script.py
So if im now directly using 'database.db' in my_module.py it points towards /main/my_module/database.db.
But if I am using my_module inside script.py it points towards /main/database.db which causes an error.
So my question is: How is it possible to have a path pointing relatively to the modules script my_module.py? (so I can use it in any place) Thanks a lot for answers!
From script.py try using os.path to get the script directory. Then you can create a relative path to the database file:
import os
maindir = os.path.dirname(__file__)
my_module_dir = os.path.join(maindir, 'my_module')
db_path = os.path.join(my_module_dir, 'database.db')
Related
My directory structure like below:
./outputsetting.json
./myapp/app.py
I load outputsetting.json file in app.py like below:
with open("..\outputpath.json","r") as f:
j=json.load(f)
And run in myapp directory it's ok:
python app.py
But if I run app.py in the parent directory:
python .\myapp\app.py
It raise error
FileNotFoundError: [Errno 2] No such file or directory: '..\\outputpath.json'
How can I load file from disk by the relative directory to the app.py? So I can run it from any place and needn't modify code every time.
Thanks!
When you start the script from the parent directory, the working directory for the script changes. If you want to access a file that has a specific location relative to the script itself, you can do this:
from pathlib import Path
location = Path(__file__).parent
with open(location / "../outputsetting.json","r") as f:
j=json.load(f)
Path(__file__) gets the location of the script it is executed in. The .parent thus gives you the folder the script is in, still as a Path object. And you can then navigate to the parent directory from that with location / "../etc"
Or of course in one go:
with open(Path(__file__).parent / "../outputsetting.json","r") as f:
j=json.load(f)
(Note: your code says outputpath.json, but I assume that's the same outputsetting.json)
Another solution would be to just change the working directory to be the folder the script is in - but that of course only works if all your scripts and modules are OK with that change:
from pathlib import Path
from os import chdir
chdir(Path(__file__).parent)
with open("../outputsetting.json","r") as f:
j=json.load(f)
I'd prefer constructing the absolute path as in the previous example though.
I have project that I decided to divide into subfolders. My main module main.py imports other module mod1.py from a subfolder. The imported module mod1.py uses images that are located in another subfolder and refers to them relatively. I can't use absolute path from the drive, but I know the relative path from the beginning of the project structure.
The situation is illustrated below somehow
project
├── main.py
└───subfolder
├───mod1.py
└───pictures
└───pic1.png
So there's a line in mod1.py:
image = Image.open("./pictures/pic1.png")
and when I import mod1.py in main.py and run the program I get an error:
FileNotFoundError: [Errno 2] No such file or directory: './pictures/pic1.png'
How to access those pictures when I run main.py and import a module that relatively refers to them?
I have __init__.py file in the subfolder and all the imports are working.
try this
try:
image = Image.open("pictures/pic1.png")
except FileNotFoundError:
image = Image.open("subfolder/pictures/pic1.png")
so python will try the first path, if it fails, it will try the second, which looks for the main.py file
While Jorge's answer may work in some cases I suggest understanding why yours does not work and look how other people have solved this problem. Lets take a very simple example.
project
dir1
test.py
dir2
test2.py
Lets assume the full path to my project directory is located at /Users/sstacha/tmp/test_python/ and my 2 test files contain the following
test.py
import os
from pathlib import Path
from dir2.test2 import function2
def function1():
path = os.getcwd()
print(f"function1.os.cwd(): {path}")
DIR = Path(__file__).resolve()
print(f"function1.pathlib_path: {DIR}")
function1()
function2()
test2.py
import os
from pathlib import Path
def function2():
path = os.getcwd()
print(f"function2.os.cwd(): {path}")
DIR = Path(__file__).resolve()
print(f"function2.pathlib_path: {DIR}")
if i execute python dir1/test.py from the project directory I get the following output:
$ python dir1/test.py
function1.os.cwd(): /Users/sstacha/tmp/test_python
function1.pathlib_path: /Users/sstacha/tmp/test_python/dir1/test.py
function2.os.cwd(): /Users/sstacha/tmp/test_python
function2.pathlib_path: /Users/sstacha/tmp/test_python/dir1/dir2/test2.py
if I instead cd to dir1 and execute python test.py I get this output:
$ python test.py
function1.os.cwd(): /Users/sstacha/tmp/test_python/dir1
function1.pathlib_path: /Users/sstacha/tmp/test_python/dir1/test.py
function2.os.cwd(): /Users/sstacha/tmp/test_python/dir1
function2.pathlib_path: /Users/sstacha/tmp/test_python/dir1/dir2/test2.py
So your actual problem is that os.cwd() will always be set to whatever directory the os was set to when the python command was run. I also included a line from how the Django settings file handles this issue for python >= 3.4. As you can see, this approach will be relative to whatever file your function is defined in which should be a better / more portable solution regardless of what directory the python executable is called from.
Hopefully that helps you understand your issue better and a possible solution that might work for you.
I realized I never really fully answered the question here would be an example:
DIR = Path(__file__).resolve().parent
image = Image.open(DIR+"/pictures/pic1.png")
By the way if you are using a version earlier than 3.4 this is how the Django settings file approached it:
DIR = os.path.dirname(os.path.abspath(__file__))
image = Image.open(DIR+"/pictures/pic1.png")
I'm in a directory called src and src has two directories:
src
/apples
/my_file.py
/carrots
functions.py
functions.py contains functions used by scripts within both apples and carrots directories.
At the top of my_file.py I initially tried to import functions but got an error 'no module named functions'.
I now understand that it's because it was in another directory, in this case just in src.
From looking at similar posts I tried this at the top of my_file.py, bearing in mind that the working directory when calling my_file.py via a shell script is the directory src:
import sys
import os
sys.path.append(os.path.abspath('/apples'))
I added a empty file init.py to /src per some responses on similar posts.
No matter what I try Python keeps telling me there is no module named functions.
I prefer a relative path since I'll be sharing this code with others and functions.py will always be in the directory above where my_file.py is.
How can I import src/functions.py within /src/apples/my_script.py?
Change your code to
import sys
sys.path.append('.')
Your problem is because the functions file is not in the path when searching from myfile it looks only for files in same directory as it
The problem is with statement to call functions file you should use it relative to myfile and not current directory
I am working on some python project (2.7) and I have issue with imports. When I run main.py it start scripts from tests folder etc. and save output to logs and everything works fine.
/root------------
-logs
-staticCfg
-config.py
-tests
-systemTest
-scrypt1.py
-scrypt2.py
-userTest
-uScrypt1.py
main.py
My static variables (email, name etc.) are located in config.py. I need to import config.py in scrypt1.py or scrypt2.py. I tryed adding __init__.py to tests, systemTest and staticCfg folder but I always get an error.
In my scrypt1.py:
import staticCfg as cfg
...
or
from staticCfg import *
...
I get the error:
ImportError: No module named staticCfg
The import mechanism of Python can be a bit tricky.
You can refer to the documentation for more information: Python Import Mechanism
When you use absolute imports (your import does not start with a .) as you do, the import path will start from your main script (the one you launch). In your case, it's scrypt1.py. So starting from this location, python can't find the package staticCfg.
For me, the simplest solution is to create a main script in your root directory and call scrypt1.py from there (imported using from tests.systemTet import scrypt1.py). In this case, the base package will be your root folder and you will have access to the package staticCfg from all your script files as you wanted to do.
you may add root folder to PYTHONPATH.
I have the following directory structure:
my_program/
foo.py
__init__.py # empty
conf/
config.cfg
__init__.py
In foo.py I have this:
import sys
#sys.path.append('conf/')
import ConfigParser
config = ConfigParser.ConfigParser()
config.read( 'conf/config.cfg' )
In conf/__init__.py I have
__all__ = ["config.cfg"]
I get this error in foo.py that I can fix by giving the full path but not when I just put conf/config.cfg but I want the relative path to work:
ConfigParser.NoSectionError
which actually means that the file can't be loaded (so it can't read the section).
I've tried commenting/un-commenting sys.path.append('conf/') in foo.py but it doesn't do anything.
Any ideas?
Paths are relative to the current working directory, which is usually the directory from which you run your program (but the current directory can be changed by your program [or a module] and it is in general not the directory of your program file).
A solution consists in automatically calculating the path to your file, through the __file__ variable that the Python interpreter creates for you in foo.py:
import os
config.read(os.path.join(os.path.dirname(__file__), 'conf', 'config.cfg'))
Explanation: The __file__ variable of each program (module) contains its path (possibly relative to the current directory when it was loaded, I guess—I could not find anything conclusive in the Python documentation—, which happens for instance when foo.py is imported from its own directory).
This way, the import works correctly whatever the current working directory, and wherever you put your package.
PS: side note: __all__ = ["config.cfg"] is not what you want: it tells Python what symbols (variables, functions) to import when you do from conf import *. It should be deleted.
PPS: if the code changes the current working directory between the time the configuration-reading module is loaded and the time you read the configuration file, then you want to first store the absolute path of your configuration file (with os.path.abspath()) before changing the current directory, so that the configuration is found even after the current directory change.
you can use os package in python for importing an absolute or relative path to the configuration file. Here is a working example with the relative path (we suppose that config.ini in the folder name configuration that is in the subdirectory of your python script folder):
import configparser
import os
path_current_directory = os.path.dirname(__file__)
path_config_file = os.path.join(path_current_directory, 'configuration', config.ini)
config = configparser.ConfigParser()
config.read(path_config_file)
Just load the path from a Variable and why so complex?
from configparser import ConfigParser
prsr=ConfigParser()
configfile="D:\Dummy\DummySubDir\Dummy.ini"
prsr.read(configfile)
print(prsr.sections())