How to use relative paths - python

I recently made a small program (.py) that takes data from another file (.txt) in the same folder.
Python file path: "C:\Users\User\Desktop\Folder\pythonfile.py"
Text file path: "C:\Users\User\Desktop\Folder\textfile.txt"
So I wrote: with open(r'C:\Users\User\Desktop\Folder\textfile.txt', encoding='utf8') as file
And it works, but now I want to replace this path with a relative path (because every time I move the folder I must change the path in the program) and I don't know how... or if it is possible...
I hope you can suggest something... (I would like it to be simple and I also forgot to say that I have windows 11)

Using os, you can do something like
import os
directory = os.path.dirname(__file__)
myFile = with open(os.path.join(directory, 'textfile.txt'), encoding='utf8') as file

If you pass a relative folder to the open function it will search for it in the loacl directory:
with open('textfile.txt', encoding='utf8') as f:
pass
This unfortunately will only work if you launch your script form its folder. If you want to be more generic and you want it to work regardless of which folder you run from you can do it as well. You can get the path for the python file being launched via the __file__ build-in variable. The pathlib module then provides some helpfull functions to get the parent directory. Putting it all together you could do:
from pathlib import Path
with open(Path(__file__).parent / 'textfile.txt', encoding='utf8') as f:
pass

import os
directory = os.path.dirname(os.path.abspath(__file__))
file_path = os.path.join(directory, 'textfile.txt')
with open(file_path, encoding='utf8') as file:
# and then the code here

Related

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.

Not showing any csv files in a folder

I'm trying to open all csv files within a given folder and then "perform a calculation". I'm currently trying to use glob but it doesn't see any files in the folder. All the code after this seems to work with a single file path but I imagine im using glob wrong.
path = "C:/build/Files*.csv"
for fileName in glob.glob(path):
with open(fileName, 'r') as file, \
open('C:PycharmProjects/Result.csv', 'r') as result_file:
#perform caluclation
I'm not sure what your file path looks like, but perhaps are you missing a /?
path = "C:/build/Files/*.csv" seems like a file structure that would be more likely.
Either make the path a raw string:
path = r"C:/build/Files*.csv"
or use double backslash:
path = "C:\\build\\Files*.csv"

Python create folder for each file in a directory

I have a directory with a set of files in it. I'm trying to create a folder for each filename inside the existing directory, and name it the given filename. but i'm getting an I/O error permission denied... what is wrong with this code?
import os
path = "C:/Users/CDGarcia/Desktop"
os.chdir(path)
gribs = os.listdir("testgrib")
print gribs
print os.getcwd()
if not os.path.exists(os.path.basename("gribs")):
os.makedirs(os.path.dirname("gribs"))
with open(path, "w") as f:
f.write("filename")
os.path.dirname() does not do what you expect it to do. It returns the directory name for the path you pass to it. So it interprets whatever string you pass as a path. As such, when you pass a path that has no directory part, it returns an empty string:
>>> os.path.dirname("gribs")
''
So with os.makedirs() you are trying to create an empty directory, which of course will not create the path you are looking for.
Instead, you should just use os.makedirs('gribs') to create gribs folder relative to your current directory.
Furthermore, open(path) will not work when path is the path to the desktop directory. You will have to pass a path to a file there. You probably meant to use a file path relative to the folder you create there:
with open('gribs/something.txt', 'w+') as f:
f.write('example content')

Open File in Another Directory (Python)

I've always been sort of confused on the subject of directory traversal in Python, and have a situation I'm curious about: I have a file that I want to access in a directory essentially parallel to the one I'm currently in. Given this directory structure:
\parentDirectory
\subfldr1
-testfile.txt
\subfldr2
-fileOpener.py
I'm trying to script in fileOpener.py to get out of subfldr2, get into subfldr1, and then call an open() on testfile.txt.
From browsing stackoverflow, I've seen people use os and os.path to accomplish this, but I've only found examples regarding files in subdirectories beneath the script's origin.
Working on this, I realized I could just relocate the script into subfldr1 and then all would be well, but my curiosity is piqued as to how this would be accomplished.
EDIT: This question pertains particularly to a Windows machine, as I don't know how drive letters and backslashes would factor into this.
If you know the full path to the file you can just do something similar to this. However if you question directly relates to relative paths, that I am unfamiliar with and would have to research and test.
path = 'C:\\Users\\Username\\Path\\To\\File'
with open(path, 'w') as f:
f.write(data)
Edit:
Here is a way to do it relatively instead of absolute. Not sure if this works on windows, you will have to test it.
import os
cur_path = os.path.dirname(__file__)
new_path = os.path.relpath('..\\subfldr1\\testfile.txt', cur_path)
with open(new_path, 'w') as f:
f.write(data)
Edit 2: One quick note about __file__, this will not work in the interactive interpreter due it being ran interactively and not from an actual file.
from pathlib import Path
data_folder = Path("source_data/text_files/")
file_to_open = data_folder / "raw_data.txt"
f = open(file_to_open)
print(f.read())
This is applicable at the time of answer, Sept. 2015
import os
import os.path
import shutil
You find your current directory:
d = os.getcwd() #Gets the current working directory
Then you change one directory up:
os.chdir("..") #Go up one directory from working directory
Then you can get a tupple/list of all the directories, for one directory up:
o = [os.path.join(d,o) for o in os.listdir(d) if os.path.isdir(os.path.join(d,o))] # Gets all directories in the folder as a tuple
Then you can search the tuple for the directory you want and open the file in that directory:
for item in o:
if os.path.exists(item + '\\testfile.txt'):
file = item + '\\testfile.txt'
Then you can do stuf with the full file path 'file'
Its a very old question but I think it will help newbies line me who are learning python.
If you have Python 3.4 or above, the pathlib library comes with the default distribution.
To use it, you just pass a path or filename into a new Path() object using forward slashes and it handles the rest. To indicate that the path is a raw string, put r in front of the string with your actual path.
For example,
from pathlib import Path
dataFolder = Path(r'D:\Desktop dump\example.txt')
Source: The easy way to deal with file paths on Windows, Mac and Linux
(unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape
import os
main_path = os.path.dirname(__file__)
file_path = os.path.join(main_path, 'subfldr1\\testfile.txt')
f = open(file_path)
I think the simplest way to search a file in another folder is:
from pathlib import Path
root_folder = Path(__file__).parents[1]
my_path = root_folder / "doc/foo.json"
with open(my_path, "r") as f:
data = json.load(f)
With parents[i] you can go back as many directories as you want without writing "../../../"
Here, I have the following architecture:
-> root
-> routes
myscript
-> doc
foo.json

File path in python

I'm trying to load the json file but it gives me an error saying No such file or directory:
with open ('folder1/sub1/sub2/sub2/sub3/file.json') as f:
data = json.load(f)
print data
The above file main.py is kept outside the folder1. All of this is kept under project folder.
So, the directory structure is Project/folder1/sub1/sub2/sub2/sub3/file.json
Where am I going wrong?
I prefer to point pathes starting from file directory
import os
script_dir = os.path.dirname(__file__)
file_path = os.path.join(script_dir, 'relative/path/to/file.json')
with open(file_path, 'r') as fi:
pass
this allows not to care about working directory changes. And also this allows to run script from any directory using it's full path.
python script/inner/script.py
or
python script.py
I would use os.path.join method to form the complete path starting from the current directory.
Something like:
json_filepath = os.path.join('.', 'folder1', 'sub1', 'sub2', 'sub3', 'file.json')
As always, an initial slash indicates that the path starts from the root. Omit the initial slash to indicate that it is a relative path.

Categories