There are two directories on my desktop, DIR1 and DIR2 which contain the following files:
DIR1:
file1.py
DIR2:
file2.py myfile.txt
The files contain the following:
file1.py
import sys
sys.path.append('.')
sys.path.append('../DIR2')
import file2
file2.py
import sys
sys.path.append( '.' )
sys.path.append( '../DIR2' )
MY_FILE = "myfile.txt"
myfile = open(MY_FILE)
myfile.txt
some text
Now, there are two scenarios. The first works, the second gives an error.
Scenario 1
I cd into DIR2 and run file2.py and it runs no problem.
Scenario 2
I cd into DIR1 and run file1.py and it throws an error:
Traceback (most recent call last):
File "<absolute-path>/DIR1/file1.py", line 6, in <module>
import file2
File "../DIR2/file2.py", line 9, in <module>
myfile = open(MY_FILE)
IOError: [Errno 2] No such file or directory: 'myfile.txt'
However, this makes no sense to me, since I have appended the path to file1.py using the command sys.path.append('../DIR2').
Why does this happen when file1.py, when file2.py is in the same directory as myfile.txt yet it throws an error? Thank you.
You can create a path relative to a module by using a module's __file__ attribute. For example:
myfile = open(os.path.join(
os.path.dirname(__file__),
MY_FILE))
This should do what you want regardless of where you start your script.
Replace
MY_FILE = "myfile.txt"
myfile = open(MY_FILE)
with
MY_FILE = os.path.join("DIR2", "myfile.txt")
myfile = open(MY_FILE)
That's what the comments your question has are referring to as the relative path solution. This assumes that you're running it from the dir one up from myfile.txt... so not ideal.
If you know that my_file.txt is always going to be in the same dir as file2.py then you can try something like this in file2..
from os import path
fname = path.abspath(path.join(path.dirname(__file__), "my_file.txt"))
myfile = open(fname)
Related
The directory structure:
├--- mod
| ├--- __init__.py
| └--- abc.data
└--- test.py
__init__.py:
with open("abc.data", 'r') as f:
pass # read and process the data
test.py:
import mod
The program above is expected to read the data in the file abc.data, but it gives an error instead:
FileNotFoundError: [Errno 2] No such file or directory: 'abc.data'
And this is because the current directory of Python interpreter is the parent directory of test.py.
So how to read abc.data in the module mod regardless of the location of test.py?
Actually the following code works:
__init__.py:
import os
filepath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "abc.data")
with open(filepath, 'r') as f:
pass # read and process the data
But this solution is a bit dirty especially when there are many files to be read in __init__.py. Is there a more elegant solution?
I believe that's as good as it gets. Even larger libraries use the same method:
# Extracted From selenium/webdriver/firefox/firefox_profile.py
# ...
if not FirefoxProfile.DEFAULT_PREFERENCES:
with open(os.path.join(os.path.dirname(__file__),
WEBDRIVER_PREFERENCES)) as default_prefs:
FirefoxProfile.DEFAULT_PREFERENCES = json.load(default_prefs)
# ...
Another example:
# Extracted from pipenv/vendor/yaspin/spinners.py
# ...
THIS_DIR = os.path.dirname(os.path.realpath(__file__))
SPINNERS_PATH = os.path.join(THIS_DIR, "data/spinners.json")
# ...
If it was an importable object (e.g. .py files) then you can use . conventions to indicate the relative path.
Example:
I have my main file, main.py with this code:
import os
os.popen("start folder/subfile.py")
Then i have my other file, subfile.py with this code:
file = open("test.txt", "w")
file.close()
I want my subfile.py to create the test.txt file in its own folder, but it creates it in the main.py's folder.
So my question is, how do i make the subfile.py run from it own folder even though it's started from main.py
main.py folder : C:/users/user/Desktop
subfile.py folder: C:/users/user/Desktop/folder
In subfile.py, change the working directory (os.chdir) to the directory that contains the subfile.py file:
import os
os.chdir(os.path.dirname(__file__))
You can use subprocess instead which has that built in:
subprocess.Popen(sys.executable + ' subfile.py', cwd=os.path.dirname(__file__) + '/folder')
Try This :
import os
import inspect
your_current_folder_path = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
your_current_file_path = os.path.join(your_current_folder_path, "test.txt")
print(your_current_folder_path)
print(your_current_file_path)
with open(your_current_file_path, "w") as make_file:
make_file.write("")
print("Done.")
Another way: you can change your working directory by os.chdir("your_folder_directory") function.
os.chdir(r"C:/users/user/Desktop/folder")
I've something like this in my program:
A main script main.py inside a folder named 'OpenFileinaModule'. There's a folder called 'sub' inside it with a script called subScript.py and a file xlFile.xlsx, which is opened by subScript.py.
OpenFileinaModule/
main.py
sub/
__init__.py (empty)
subScript.py
xlFile.xlsx
Here is the code:
sub.Script.py:
import os, openpyxl
class Oop:
def __init__(self):
__file__='xlFile.xlsx'
__location__ = os.path.realpath(
os.path.join(os.getcwd(), os.path.dirname(__file__)))
print os.path.join(__location__, __file__)
self.wrkb = openpyxl.load_workbook(os.path.join(__location__,
__file__),read_only=True)
main.py:
import sub.subScript
objt=sub.subScript.Oop()
When I execute main.py, I get the error:
IOError: [Errno 2] No such file or directory: 'C:\\Users\\...\\OpenFileInaModule\\xlFile.xlsx'
It jumps the sub folder...
I've tried
__file__='sub/xlFile.xlsx'
But then the "sub" folder is duplicated:
IOError: [Errno 2] No such file or directory: 'C:\\Users\\...\\OpenFileInaModule\\sub\\sub/xlFile.xlsx'
How to open xlFile.xlsx with subScript.py from main.py?
you're overriding __file__ with __file='xlFile.xlsx', do you mean to do this?
I think you want something like
import os
fname = 'xlFile.xlsx'
this_file = os.path.abspath(__file__)
this_dir = os.path.dirname(this_file)
wanted_file = os.path.join(this_dir, fname)
I'd suggest always using the absolute path for a file, especially if you're on windows when a relative path might not make sense if the file is on a different drive (I actually have no idea what it would do if you asked it for a relative path between devices).
Please avoid using __file__ and __location__ to name your variables, these are more like builtin variables which might cause a confusion.
Note something here:
__location__ = os.path.realpath(
os.path.join(os.getcwd(), os.path.dirname(__file__)))
You have not included sub directory and the above joins only the CWD + os.path.dirname(__file__). This doesn't get you to the file. Please read the documentation of os.path.dirname: os.path.dirname(__file__) returns an empty string here.
def __init__(self):
file = 'xlFile.xlsx'
location = os.path.join('sub', file)
location = os.path.abspath(location) # absolute path to file
location = os.path.realpath(location) # rm symbolic links in path
self.wrkb = openpyxl.load_workbook(location)
Folder Structure
Project_Folder -|
Scripts-|
images -|
file.py
Inside file.py
import requests
import os
import sys
sys.path.append('.')
url = "http://d2np4vr8r37sds.cloudfront.net/800313-kkenlukmjy-1481094947.jpg"
image = requests.get(url)
IMG_DIR = 'images'
IMG_DIR_ABS = os.path.join('.', IMG_DIR)
filename = "800313-kkenlukmjy-1481094947.jpg"
fullfilename = os.path.join(IMG_DIR_ABS, filename)
with open(fullfilename, 'wb') as f:
f.write(image.content)
f.close()
When I am running this code I am getting following error
python scripts/file.py
Traceback (most recent call last):
File "scripts/file.py", line 9, in <module>
with open(fullfilename, 'wb') as f:
IOError: [Errno 2] No such file or directory: './images/800313-kkenlukmjy-1481094947.jpg'
IMG_DIR_ABS = os.path.join('.', IMG_DIR) does not resolve the location of the current script. . is the current directory, not the directory of the current script.
What you want to do is:
IMG_DIR_ABS = os.path.join(os.path.dirname(__file__), IMG_DIR)
__file__ being the full filepath of the currently running script, which matches your expectations given your directory tree.
the advantage of this method is that you can launch your script from any directory.
Aside: no need for f.close() within the with block. with context handles that for you when exiting the block.
You are running your script from Project_Folder, but there is no such path './images/800313-kkenlukmjy-1481094947.jpg' if You look from that directory. Try using './scripts/images/800313-kkenlukmjy-1481094947.jpg' instead.
I have the following file structure:
test/
test1.py
test2.py
text.txt
Here are the contents of the files
test1.py:
import sys
sys.path.append('../')
import test2
test2.read()
test2.py:
def read():
with open('text.txt', 'rb') as f:
print f.read()
if __name__ == "__main__":
read()
text.txt contains a line of text. When I run test1.py, I get a "File not found" error:
Traceback (most recent call last):
File "test1.py", line 5, in <module>
test2.read()
File "../test2.py", line 2, in read
with open('text.txt', 'rb') as f:
IOError: [Errno 2] No such file or directory: 'text.txt'
I kind of understand why this error is coming up. But how do I deal with these kind of errors. I would like the code in test2.py to be like library code which I can use anywhere.
sys.path used for python path (PYTHONPATH eviroment variable).
i.e. where to look for python libraries when you import some library.
it dose not effect where open() is looking for files.
when you open(filename). the filename is relative to the procees working directory. (the path the code was run from)
so if you want to access a flie that its path is relative to the path of the code file, then you can use the builtin variable __file__ which hold the current file path.
so you can change test2.py to be:
import os
def read():
with open(os.path.join(os.path.dirname(__file__),'text.txt'), 'rb') as f:
print f.read()
The proper way of doing what you're asking for is to use pkg_resources as described here. Basically something like the following would be what you want in test2.py:
import pkg_resources
def read():
with pkg_resources.resource_stream(__name__, 'text.txt') as f:
print f.read()
if __name__ == "__main__":
read()
Don't use relative path, then. Use the full path:
with open(r'C:\Somewhere\someplace\test.txt') as f: