I have a python file in "mainDirectory/subdirectory/myCode.py" and in my code, I want to refer to a .csv file in "mainDirectory/some_data.csv" I don't want to use an absolute path since I run the code in different operating systems and using absolute path may make trouble. so in short, is there a way to refer to the upper directory of the current directory using a relative path in python?
I know how to refer to the subdirectories of the current directory using a relative path. but I'm looking for addressing to the upper-level directories using the relative path. I don't want to use absolute bath since the file is going to be run in different folders in different operating systems.
Update:
I found one method here (it is not based on the relative path but it does the job):
the key is using "." for importing upper hand directories.
for example, one can access the same layer directory by using one dot. for accessing the one-layer higher, one can use two dots. in the above case, to access the "subdirectory" one can put this line in "myCode.py"
from .subdirectory import something
to access the "mainDirectory:
from ..mainDirectory import something
If you look at the Python documentation, you will find that the language is not designed to be used like that. Instead you'll want to try to refactor your directories to put myCode.py in a parent level directory like mainDirectory.
mainDirectory
│
└───myCode.py
│
└───subdirectory
│
│ some_data.csv
You are facing an issue with the nature of the PYTHONPATH. There is a great article on dealing with PYTHONPATH here:
https://chrisyeh96.github.io/2017/08/08/definitive-guide-python-imports.html
It can be challenging if you're new to the language (or if you've been using it for years!) to navigate Python import statements. Reading up on PEP8 conventions for importing, and making sure your project conforms to standard language conventions can save you a lot of time, and a lot of messy git commits when you need to refactor your directory tree down the line.
You can always derive absolute path at run time using API provided by os package.
import os
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'relative/path/to/file/you/want')
Complete answer was always a click away. Relative paths in Python
There are several tools in os.path that you can use:
from os.path import dirname
upper = dirname(dirname(__filepath__))
Here is alink to a more comprehensive answer on accessing upper directories:
How do I get the parent directory in Python?
Related
Here's the theoretical scenario:
Project_A and Project_B are two independent processes for the client. Both projects rely on a custom module called Module_X.
I have the following folder structure currently :
project_a
project_a/module_x
project_b
project_b/module_x
This functionally works but has the drawback of if I do a change in project_b/module_x I then have to manually copy over the updated contents of module_x to project_a/module_x so that they are congruent and I get consistent results between the two projects.
What is a better way in which I can handle this?
module_x is not able to be put up on pypi as it contains logic for sensitive information resources.
This will add that path to paths where python searches for modules
import sys
sys.path.insert(1, '/home/user/projectb')
This is the most similar question I could find, and it's 5 years old with no answer.
I have a PyCharm project where most of my imports are relative, like this:
from .. import something
However, new ones automatically added are absolute:
from project.other_package import something
Since I find absolute imports clearer, I wouldn't mind converting all the relative imports to absolute ones, but there seems to be no way to do so.
Is it possible to automatically convert all relative imports in a PyCharm project into absolute ones?
Right click into the line where the relative import is located, then click to "Show context actions". You will see the option to convert relative import to absolute one. Unfortunately you have to do this one by one.
Another solution would be renaming your package name (using refactor) then returning back to original package name. PyCharm cannot work out relative imports when you change top level package name so it converts all imports to absolute. When you rename your package again the desired result will be achieved. Be careful though, this might break some other parts of the code.
I have the following directory structure:
TestFolder:
test.py
CommonFolder:
common.py
And in test.py, I need to import common.py.
In order to do that, in test.py I add the path of CommonFolder to the system paths.
Here is what I started off with:
sys.path.append(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'CommonFolder'))
Then I figured that / is a valid separator in pretty much every OS, so I changed it to:
sys.path.append(os.path.dirname(os.path.dirname(__file__)) + '/CommonFolder')
Then I figured that .. is also a valid syntax in pretty much every OS, so I changed it to:
sys.path.append(os.path.dirname(__file__) + '/../CommonFolder')
My questions:
Are my assumptions above correct, and will the code run correctly on every OS?
In my last change, I essentially add a slightly longer path to the system paths. More precisely - FullPath/TestFolder/../CommonFolder instead of FullPath/CommonFolder. Is the any runtime impact to this? I suppose that every import statement might be executed slightly slower, but even if so, that would be minor. Is there any good reason not to do it this way?
If you're writing code to span multiple Operating Systems it's best not to try to construct the paths yourself. Between Linux and Windows you immediately run into the forward vs backwards slash issue, just as an example.
I'd recommend looking into the Python pathlib library. It handles generating paths for different operating systems.
https://docs.python.org/3/library/pathlib.html
This is a great blog about this subject and how to use the library:
https://medium.com/#ageitgey/python-3-quick-tip-the-easy-way-to-deal-with-file-paths-on-windows-mac-and-linux-11a072b58d5f
UPDATE:
Updating this with a more specific answer.
Regarding the directory paths, as long as you're not building the paths yourself (using a utility such as pathlib) the paths you've created should be fine. Linux, Mac, and Windows all support relative paths (both mac and linux are Unix ~based of course).
As for whether it's efficient, unless you're frequently dynamically loading or reloading your source files (which is not common) most files are loaded into memory before the code is run, so there would be no performance impact on setting up the file paths in this way.
Use os.path.join() for OS independent path separator instead of /
Example: os.path.join(os.path.dirname(__file__),"..","CommonFolder")
Or instead you can make CommonFolder as python package by just placing a empty file by name __init__.py inside CommonFolder. After that you can simply import common in test.py as:-
from CommonFolder import common
Can someone explain what is the difference in using
filepath = 'C:/Users/your_name/Documents/subfolder/'
to
filepath = '~/Documents/subfolder/'
?
I am writing code that I'd like to be re-useable on a second computer with an identical folder structure, but different location of the Documents folder.
The following pages on SO appear to give indications on how to do it differently, but I'm wondering about how much better these are versus the method shown above. From an SO/Google point of view, searching for "~" has not lead to any useful answers either.
How to get an absolute file path in Python
Relative imports for the billionth time
Find current directory and file's directory
If the path is the same past the user name, then ~ would be best, you just have to make sure that you expand it before passing to routines that expect abs path.
In general ~ is just an environment variable to the user home directory that is currently in session, and to expand it just call something like:
os.path.expandvars("~\your\tilde\path")
I have a python module that is shared among several of my projects (the projects each have a different working directory). One of the functions in this shared module, executes a script using os.spawn. The problem is, I'm not sure what pathname to give to os.spawn since I don't know what the current working directory will be when the function is called. How can I reference the file in a way that any caller can find it? Thanks!
So I just learned about the __file__ variable, which will provide a solution to my problem. I can use file to get a pathname which will be constant among all projects, and use that to reference the script I need to call, since the script will always be in the same location relative to __file__. However, I'm open to other/better methods if anyone has them.
Put it in a well known directory (/usr/lib/yourproject/ or ~/lib or something similar), or have it in a well known relative path based on the location of your source files that are using it.
The following piece of code will find the location of the calling module, which makes sense from a programmer's point of view:
## some magic to allow paths relative to calling module
if path.startswith('/'):
self.path = path
else:
frame = sys._getframe(1)
base = os.path.dirname(frame.f_globals['__file__'])
self.path = os.path.join(base, path)
I.e. if your project lives in /home/foo/project, and you want to reference a script 'myscript' in scripts/, you can simply pass 'scripts/myscript'. The snippet will figure out the caller is in /home/foo/project and the entire path should be /home/foo/projects/scripts/myscript.
Alternatively, you can always require the programmer to specify a full path, and check using os.path.exists if it exists.
You might find the materials in this PyCon 2010 presentation on cross platform application development and distribution useful. One of the problems they solve is finding data files consistently across platforms and for installed vs development checkouts of the code.