Absolute Path and Relative Path issue in python - python

How to remove path related problems in python?
For e.g. I have a module test.py inside a directory TEST
**test.py**
import os
file_path = os.getcwd() + '/../abc.txt'
f = open(file_path)
lines = f.readlines()
f.close
print lines
Now, when I execute the above program outside TEST directory, it gives me error:-
Traceback (most recent call last):
File "TEST/test.py", line 4, in ?
f = open(file_path)
IOError: [Errno 2] No such file or directory: 'abc.txt'
how to resolve this kind of problem. Basically this is just a small example that I have given up.
I am dealing with a huge problem of this kind.
I am using existing packages, which needs to be run only from that directory where it exists, how to resolve such kind of problems, so that I can run the program from anywhere I want.
Or able to deal with the above example either running inside TEST directory or outside TEST directory.
Any help.?

I think the easiest thing is to change the current working directory to the one of the script file:
import os
os.chdir(os.path.dirname(__file__))
This may cause problems, however, if the script is also working with files in the original working directory.

Your code is looking at the current working directory, and uses that as a basis for finding the files it needs. This is almost never a good idea, as you are now finding out.
The solution mentioned in the answer by Emil Vikström is a quickfix solution, but a more correct solution would be to not use current working directory as a startingpoint.
As mentioned in the other answer, __file__ isn't available in the interpreter, but it's an excellent solution for your code.
Rewrite your second line to something like this:
file_path = os.path.join(os.path.dirname(__file__), "..", "abc.txt")
This will take the directory the current file is in, join it first with .. and then with abc.txt, to create the path you want.
You should fix similar usage of os.getcwd() elsewhere in your code in the same way.

Related

Python - File Path not found if script run from another directory

I'm trying to run a script that works without issue when I run using in console, but causes issue if I try to run it from another directory (via IPython %run <script.py>)
The issue comes from this line, where it references a folder called "Pickles".
with open('Pickles/'+name+'_'+date.strftime('%y-%b-%d'),'rb') as f:
obj = pickle.load(f)
In Console:
python script.py <---works!
In running IPython (Jupyter) in another folder, it causes a FileNotFound exception.
How can I make any path references within my scripts more robust, without putting the whole extended path?
Thanks in advance!
Since running in the console the way you show works, the Pickles directory must be in the same directory as the script. You can make use of this fact so that you don't have to hard code the location of the Pickles directory, but also don't have to worry about setting the "current working directory" to be the directory containing Pickles, which is what your current code requires you to do.
Here's how to make your code work no matter where you run it from:
with open(os.path.join(os.path.dirname(__file__), 'Pickles', name + '_' + date.strftime('%y-%b-%d')), 'rb') as f:
obj = pickle.load(f)
os.path.dirname(__file__) provides the path to the directory containing the script that is currently running.
Generally speaking, it's a good practice to always fully specify the locations of things you interact with in the filesystem. A common way to do this as shown here.
UPDATE: I updated my answer to be more correct by not assuming a specific path separator character. I had chosen to use '/' only because the original code in the question already did this. It is also the case that the code given in the original question, and the code I gave originally, will work fine on Windows. The open() function will accept either type of path separator and will do the right thing on Windows.
You have to use absolute paths. Also to be cross platform use join:
First get the path of your script using the variable __file__
Get the directory of this file with os.path.dirname(__file__)
Get your relative path with os.path.join(os.path.dirname(__file__), "Pickles", f"{name}_{date.strftime('%y-%b-%d')}")
it gives you:
with open(os.path.join(os.path.dirname(__file__), "Pickles", f"{name}_{date.strftime('%y-%b-%d')}"), 'rb') as f:
obj = pickle.load(f)

Not finding any solution to [Errno 2]

I'm trying to use a program to read from a file with pi-digits. The program and the text file with the pi-digits are in the same directory, but i still get the error message :
with open('pi_digits.txt') as file_object:
contents = file_object.read()
print(contents.rstrip())
Traceback (most recent call last):
File "C:\Python\Python_Work\python_crash_course\files_and_exceptions\file_reader.py", line 1, in <module>
with open('pi_digits.txt') as file_object:
FileNotFoundError: [Errno 2] No such file or directory: 'pi_digits.txt'
I have looked for a solution but haven't found any.
I found a piece of code which supposedly shows me what the working directory is. I get an output that shows a directory that is 2 steps above the directory i have my programs and text file inside.
import os
cwd = os.getcwd() # Get the current working directory (cwd)
files = os.listdir(cwd) # Get all the files in that directory
print("Files in %r: %s" % (cwd, files))
So when i put the pi text document in the directory that the output is showing (>python_work), the program is working. When it does not work is when the text file is in ">files_and_exceptions" which is the same file the program itself is inside. My directory looks like this when it is not working:
>python_work
>python_crash_course
>files_and_exceptions
file_reader.py
pi_digits.txt
show_working_directory.py
And like this when it is working:
>python_work
pi_digits.txt
>python_crash_course
>files_and_exceptions
file_reader.py
show_working_directory.py
I'm new to python and really appreciate any help.
Thanks!
Relative path (one not starting with a leading /) is relative to some directory. In this case (and generally*), it's relative to the current working directory of the process.
In your case, given the information you've provided, for it would be "python_crash_course/files_and_exceptions/pi_digits.txt" in the first case as you appear to be running the script from python_work directory.
If you know the file to be in the same directory as the script itself, you could also say:
import os.path
...
os.path.join(os.path.dirname(__file__), "pi_digits.txt")
instead of "pi_digits.txt". Or the same using pathlib:
from pathlib import Path
...
Path(__file__).with_name("pi_digits.txt")
Actually unless you have a point to anchor to like the script itself, using relative filename / path (using absolute paths brings its own problems too) in the code directly is rather fragile and in that case getting it as a parameter of a function (and ultimately argument of CLI or script call in general) or alternatively reading it from standard input would be more robust.
* I would not make that an absolute statement, because there are situations and functions that can explicitly provide different anchor point (e.g. os.path.relpath or openat(2); or as another example a symlink target)

Regarding file io in Python

I mistakenly, typed the following code:
f = open('\TestFiles\'sample.txt', 'w')
f.write('I just wrote this line')
f.close()
I ran this code and even though I have mistakenly typed the above code, it is however a valid code because the second backslash ignores the single-quote and what I should get, according to my knowledge is a .txt file named "\TestFiles'sample" in my project folder. However when I navigated to the project folder, I could not find a file there.
However, if I do the same thing with a different filename for example. Like,
f = open('sample1.txt', 'w')
f.write('test')
f.close()
I find the 'sample.txt' file created in my folder. Is there a reason for the file to not being created even though the first code was valid according to my knowledge?
Also is there a way to mention a file relative to my project folder rather than mentioning the absolute path to a file? (For example I want to create a file called 'sample.txt' in a folder called 'TestFiles' inside my project folder. So without mentioning the absolute path to TestFiles folder, is there a way to mention the path to TestFiles folder relative to the project folder in Python when opening files?)
I am a beginner in Python and I hope someone could help me.
Thank you.
What you're looking for are relative paths, long story short, if you want to create a file called 'sample.txt' in a folder 'TestFiles' inside your project folder, you can do:
import os
f = open(os.path.join('TestFiles', 'sample1.txt'), 'w')
f.write('test')
f.close()
Or using the more recent pathlib module:
from pathlib import Path
f = open(Path('TestFiles', 'sample1.txt'), 'w')
f.write('test')
f.close()
But you need to keep in mind that it depends on where you started your Python interpreter (which is probably why you're not able to find "\TestFiles'sample" in your project folder, it's created elsewhere), to make sure everything works fine, you can do something like this instead:
from pathlib import Path
sample_path = Path(Path(__file__).parent, 'TestFiles', 'sample1.txt')
with open(sample_path, "w") as f:
f.write('test')
By using a [context manager]{https://book.pythontips.com/en/latest/context_managers.html} you can avoid using f.close()
When you create a file you can specify either an absolute filename or a relative filename.
If you start the file path with '\' (on Win) or '/' it will be an absolute path. So in your first case you specified an absolute path, which is in fact:
from pathlib import Path
Path('\Testfile\'sample.txt').absolute()
WindowsPath("C:/Testfile'sample.txt")
Whenever you run some code in python, the relative paths that will be generate will be composed by your current folder, which is the folder from which you started the python interpreter, which you can check with:
import os
os.getcwd()
and the relative path that you added afterwards, so if you specify:
Path('Testfiles\sample.txt').absolute()
WindowsPath('C:/Users/user/Testfiles/sample.txt')
In general I suggest you use pathlib to handle paths. That makes it safer and cross platform. For example let's say that your scrip is under:
project
src
script.py
testfiles
and you want to store/read a file in project/testfiles. What you can do is get the path for script.py with __file__ and build the path to project/testfiles
from pathlib import Path
src_path = Path(__file__)
testfiles_path = src_path.parent / 'testfiles'
sample_fname = testfiles_path / 'sample.txt'
with sample_fname.open('w') as f:
f.write('yo')
As I am running the first code example in vscode, I'm getting a warning
Anomalous backslash in string: '\T'. String constant might be missing an r prefix.
And when I am running the file, it is also creating a file with the name \TestFiles'sample.txt. And it is being created in the same directory where the .py file is.
now, if your working tree is like this:
project_folder
-testfiles
-sample.txt
-something.py
then you can just say: open("testfiles//hello.txt")
I hope you find it helpful.

How do I fix the "No File or Directory issue" python?

Beginner to python here.
I am writing a program that involves opening and reading input from another file. The python file is called paint.py, while my input file is paint_test.in
fn = open('paint_test.in', 'r')
Whenever I try running that code, it gives me a "No file or directory error".
The full path to my folder containing both these files: C:\Users\ayush\Desktop\USACO\paint
I would appreciate it if anyone could point me in the right direction here. Thanks!
The file is not found because it is looking in the current directory, which is not the same directory where your script lives.
Depending on how you run Python, the current directory might be where the python executable program itself lives, or some other generic directory such as C:\.
One way around this problem is to use the full directory path to the filename:
fn = open('C:/Users/ayush/Desktop/USACO/paint/paint_test.in', 'r')
(Yes, forward slashes will work, and they're safer than backslashes, because you don't have to worry about certain combinations such as \n or \b being interpreted in a special way.)
That should not cause an error. Maybe you could try this giving an absolute path:
fn = open('C:\Users\ayush\Desktop\USACO\paint\paint_test.in', 'r')

Making a new file in subdirectories using python

I am trying to create a file in a subdirectory, both of which will not exist when the program is first run. When I do this:
newfile = open('abc.txt','w')
It will create abc.txt just fine but the following will cause an error, saying the file or directory does not exist
newfile = open('folder/abc.txt','w')
I tried using os.makedirs to create the directory first but that failed as well raising the same error. What is the best way to create both the folder and file?
Thanks
>>> import os
>>> os.makedirs('folder')
>>> newfile = open('folder' + os.sep + 'abc.txt', 'w')
>>> newfile.close()
>>> os.listdir('folder')
['abc.txt']
This works for me
A couple of things to check:
os.makedirs takes just the path, not the file. I assume you know this already, but you haven't shown your call to makedirs so I thought I'd mention it.
Consider passing an absolute, not a relative, path to makedirs. Alternatively, use os.chdir first, to change to a directory in which you know you have write permission.
Hope those help!

Categories