How to generate path of a directory in python - python

I have a file abc.py under the workspace dir.
I am using os.listdir('/home/workspace/tests') in abc.py to list all the files (test1.py, test2.py...)
I want to generate the path '/home/workspace/tests' or even '/home/workspace' instead of hardcoding it.
I tried os.getcwd() and os.path.dirname(os.path.abspath(____file____)) but this instead generates the path where the test script is being run.
How to go about it?

The only way you can refer to a specific folder from which you don't relate in any way and you don't want to hardcode it, is to pass it as a parameter to the script (search for: command line argument)

I think you are asking about how to get the relative path instead of absolute one.
Absolute path is the one like: "/home/workspace"
Relative looks like the following "./../workspace"
You should construct the relative path from the dir where your script is (/home/workspace/tests) to the dir that you want to acces (/home/workspace) that means, in this case, to go one step up in the directory tree.
You can get this by executing:
os.path.dirname(os.path.join("..", os.path.abspath(__file__)))
The same result may be achieved if you go two steps up and one step down to workspace dir:
os.path.dirname(os.path.join("..", "..", "workspace", os.path.abspath(__file__)))
In this manner you actually can access any directory without knowing it's absolute path, but only knowing where it resides relatively to your executed file.

Related

list of name and path of files in a directory and subdirectory where one or more subdir have a point in the middle python

I'm trying to get path and filename, from a directory, including those ones inside the subdirectories. The problem is that some subfolders have one or more points in the name.
So when I execute this code
listaFile=glob.glob('c:\test\ID_1'+/**/*.*',recursive= True)
I get
c:\test\ID_1\fil.e1.txt
c:\test\ID_1\fil.e2.doc
c:\test\ID_1\subfolder1\file1.txt
c:\test\ID_1\sub.folder2 (instead of c:\test\ID_1\sub.folder2\file1.txt)
thank you all in advance!
You need to filter it out checking if it's a file or folder. An easy way would be to use the pathlib instead of glob directly. Example below.
listaFile = [str(path) for path in pathlib.Path(r"c:\test\ID_1").rglob("*.*") if path.is_file()]

Navigating directories

After getting the path to the current working directory using:
cwd = os.getcwd()
How would one go up one folder: C:/project/analysis/ to C:/project/ and enter a folder called data (C:/project/data/)?
In general it a bad idea to 'enter' a directory (ie change the current directory), unless that is explicity part of the behaviour of the program.
In general to open a file in one directory 'over from where you are you can do .. to navigate up one level.
In your case you can open a file using the path ../data/<filename> - in other words use relative file names.
If you really need to change the current working directory you can use os.chdir() but remember this could well have side effects - for example if you import modules from your local directory then using os.chdir() will probably impact that import.
As per Python documentation, you could try this:
os.chdir("../data")

What is the pythonic way to get file handles from the command line with relative or absolute paths?

When I write a command line script in python, I'm assuming that it can be invoked from anywhere. This seems to cause incongruity when I want to pass a list of files into the script.
Passing the files using a list or wildcard arguments (whether expanded by bash under *nix or glob.glob with Windows) will return either a relative path or an absolute one, depending on how the file path was described, but this seems to give two different behaviors which have to either be checked or harmonized.
If the script is in the same directory as the files to be imported, this isn't really a problem, but if the script is in a different directory, it seems like you need to grab the absolute path first:
import os,sys,glob
for arg in sys.argv[1:]:
file_list = glob.glob(arg)
for fn in file_list:
print("File Reference: {}".format(os.path.abspath(fn)))
> pwd
/Users/user1/Desktop/script_dir/
> cd ~/Desktop
> script_dir/test.py test_dir/*.csv /Users/user1/Desktop/test_dir/*.txt
File Reference: /Users/user1/Desktop/test_dir/temp1.csv
File Reference: /Users/user1/Desktop/test_dir/temp2.csv
File Reference: /Users/user1/Desktop/test_dir/temp1.txt
File Reference: /Users/user1/Desktop/test_dir/temp2.txt
Assuming the program continued on to do something with the files, it would then manipulate them by absolute path. Is this the correct thing to do here? It seems weirdly klugy, and I can seem to find any references that lay this out.

Weird python file path behavior

I have this folder structure, within edi_standards.py I want to open csv/transaction_groups.csv
But the code only works when I access it like this os.path.join('standards', 'csv', 'transaction_groups.csv')
What I think it should be is os.path.join('csv', 'transaction_groups.csv') since both edi_standards.py and csv/ are on the same level in the same folder standards/
This is the output of printing __file__ in case you doubt what I say:
>>> print(__file__)
~/edi_parser/standards/edi_standards.py
when you're running a python file, the python interpreter does not change the current directory to the directory of the file you're running.
In your case, you're probably running (from ~/edi_parser):
standards/edi_standards.py
For this you have to hack something using __file__, taking the dirname and building the relative path of your resource file:
os.path.join(os.path.dirname(__file__),"csv","transaction_groups.csv")
Anyway, it's good practice not to rely on the current directory to open resource files. This method works whatever the current directory is.
I do agree with Answer of Jean-Francois above,
I would like to mention that os.path.join does not consider the absolute path of your current working directory as the first argument
For example consider below code
>>> os.path.join('Functions','hello')
'Functions/hello'
See another example
>>> os.path.join('Functions','hello','/home/naseer/Python','hai')
'/home/naseer/Python/hai'
Official Documentation
states that whenever we have given a absolute path as a argument to the os.path.join then all previous path arguments are discarded and joining continues from the absolute path argument.
The point I would like to highlight is we shouldn't expect that the function os.path.join will work with relative path. So You have to submit absolute path to be able to properly locate your file.

Relative path in Python

I'm writing some python code to generate the relative path. Situation need to be considered:
Under the same folder. I want "." or ".\", both of tham are ok for me.
Other folder. I want like ".\xxx\" and "..\xxx\xxx\"
os.path.relpath() will generate the relative path, but without .\ at the beginning and \ in the end. We can add \ in the end by using os.path.join(dirname, ""). But i can't figure out how to add ".\" at the beginning without impacting the first case when they are under the same folder and "..\xxx\xxx\".
It will give you relative path
import os
dir = os.path.dirname(__file__)
filename = os.path.join(dir,'Path')
The relpath() function will produce the ".." syntax given the appropriate base to start from (second parameter). For instance, supposing you were writing something like a script generator that produces code using relative paths, if the working directory is as the second parameter to relpath() as below indicates, and you want to reference in your code another file in your project under a directory one level up and two deep, you'll get "../blah/blah".. In the case where you want to prefix paths in the same folder, you can simply do a join with ".". That will produce a path with the correct OS specific separator.
print(os.path.relpath("/foo/bar/blah/blah", "/foo/bar/baz"))
>>> ../blah/blah
print(os.path.join('.', 'blah'))
>>> ./blah

Categories