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.
Related
so I recently tried using playsound and the .mp3 is in the same folder as the .py, and it says it could not find the file.
I printed out the current directory and it says it's at C:\Users\me
Shouldn't this be at the same directory as where the .py script is at? This has been happening with my other python scripts where I have to explicitly give it the directory, whereas before I didn't have to and it was just where the python script was at.
Is there a setting for this?
The current directory is defined by where you execute the python file not the location of it. If you want to change the directory you can use the os module:
import os
os.chdir(PATH)
If you're looking for a file in the same directory as the executing python program:
basename = os.path.basename(__file__)
my_file_name = basename + "/myfile"
with open(my_file_name) as my_file:
...
The variable __file__ contains the full pathname of the currently executing Python program.
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")
My tests are at:
src/com/xyz/tests/api_test/<Test File>
My test file calls my libraries at:
src/com/xyz/libs/api_libs/<Library File>
My library file has to open a JSON file at:
src/com/xyz/libs/api_libs/configs/<Config File>
In my library file, since its at the same parent directory as the JSON configs, I have used the following code to open the JSON.
with open('configs/sample_wlan_json'):
<Do Some action>
I tried various paths like:
.../libs/api_libs/configs/<ConfigFileName>
src/com/mist/libs/api_libs/configs/<ConfigFileName>.json
The whole path from /Users/...... but nothing seems to work.
A relative path is relative to the current working directory. Current working directory depends on how an application is started, and not where it is.
So, if you want to have a path relative to your source code, you should not rely on the current working directory, but construct the absolute path instead.
You can construct a path which is relative to your source code by using the __file__ variable, which is the path to the current py file.
Something like this should work:
configs_dir = os.path.join(__file__, '..', 'configs')
with open(os.path.join(configs_dir, 'sample_wlan.json'), 'rt') as f:
...
I just experienced a weird behaviour in Python.
I created a copy of a script.py file in a sub-folder within the folder that contains the initial script.
The script at the end exports some data into a .txt file by using:
with open('clayList.2203.txt', 'w',encoding='utf-8') as f:
for item in claysUniqueList:
f.write("%s\n" % item)
The problem is that Python writes the new file on the parent directory instead of the current one.
I checked the path with:
print(sys.path[0])
and it prints the current path correctly.
By default, relative paths are relative to the working directory, that is the directory from which is run the command that run the script.
If you want the path to be relative from the script directory, you will have to explicitly code this behaviour:
import os
filepath = os.path.join(os.path.dirname(__file__), 'clayList.2203.txt')
with open(filepath, 'w',encoding='utf-8') as f:
# ...
When you run code in Visual Studio, there are debugging options.
One of these it the directory to run from, called "Working directory".
(Right click your project and go to settings).
To run from the sub-directory you need to change this.
If you want to start in a sub directory, type that in instead, in the "working directory" shown here:
path for creating the file should be relative to the directory of execution
e.g. your pwd is parent and your script is in parent/child1/child2/script.py then path of the file to be created should be ./child1/child2/clayList.2203.txt
I've built a script to read an excel file and save the contents into my database. (Note: the file and the script are in different directories). However, when I try to execute the script from my views.py as a simple import, django throws an error that it cannot find the file or directory:
[Errno 2] No such file or directory: '\\media\\documents\\GDRAT.xls\\'
My actual code in the script looks like this:
source_wb = xlrd.open_workbook('media/documents/GDRAT.xls')
Where my script is in the parent directory. Executing the script from the command line works just fine, so I'm struggling with why django is reading it differently.
My views.py function looks like this (Note: I go back to the parent directory to find the script - which seems to work fine, just can't find the excel file I need to read in):
def UpdateGDRAT(request):
os.chdir('..')
import GDRAT
return render_to_response('success.html')
Any guidance is greatly appreciated!
This works for me
os.path.join(os.path.dirname(os.path.dirname(__file__)),'media/documents/GDRAT.xls')
settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
from django.conf import settings
import os
base_dir =settings.MEDIA_ROOT
my_file = os.path.join(base_dir, str(GDRAT.xls))
when you run a script from the terminal, you have a current working directory from which any relative path starts, when calling the same script from another code your working directory could be different.
If you know the position of the file relative to the script, I suggest you to use an absolute path constructed dynamically like this:
import os
GDRAT_abs_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'media/documents/GDRAT.xls')
__file__ gives you the path of the current file that is the script (assuming this line is placed in the script);
for dirname see http://docs.python.org/2/library/os.path.html#os.path.dirname
for realpath see http://docs.python.org/2/library/os.path.html#os.path.realpath