How to get higher directory folder in python project? - python

It drives me crazy so I decided to ask here. I need to save the generated txt file (from lower structures of the project), to folder which is the sibling of the parent directory. I have used variety of different code along with all possibiliteis given by os.path.join etc and still nothing.
My structure:
--reports
--parent folder
--another folder
--another folder
-file.py
My lates code (based on string):
abs_dir = str(Path(__file__))
i = abs_dir.index("master")
self.new_dir = os.path.join(abs_dir[:i]+f"reports//log({self.date}).txt")

Use double dots (..), that will go to the parent directory
If you want to get to a folder in a parent folder
f1
- file.py
f2
- a.txt
you could just do ../f2/a.txt
In your case, you would have to go 3 folders up: ../../../reports/log...

Related

How can I import a csv from another folder in python?

I have a script in python, I want to import a csv from another folder. how can I do this? (for example, my .py is in a folder and I want to reach the data from the desktop)
First of all, you need to understand how relative and absolute paths work.
I write an example using relative paths. I have two folders in desktop called scripts which includes python files and csvs which includes csv files. So, the code would be:
df = pd.read_csv('../csvs/file.csv)
The path means:
.. (previous folder, in this case, desktop folder).
/csvs (csvs folder).
/file.csv (the csv file).
If you are on Windows:
Right-click on the file on your desktop, and go to its properties.
You should see a Location: tag that has a structure similar to this: C:\Users\<user_name>\Desktop
Then you can define the file path as a variable in Python as:
file_path = r'C:\Users\<your_user_name>\Desktop\<your_file_name>.csv'
To read it:
df = pd.read_csv(file_path)
Obviously, always try to use relative paths instead of absolute paths like this in your code. Investing some time into learning the Pathlib module would greatly help you.

How to use data files of sub-directories and perform iterative operation in python

I have my jupyter notebook (python script) in current directory. In current directory, I have two subfolders, namely a and b. In both directories a and b I have equal number of .dat files with same names. For example, directory a contains files, namely x1-x1-val_1, x1-x1-val_5, x1-x1-val_11...x1-x1-val_86 and x1-x2-val_1, x1-x2-val_5, x1-x2-val_11...x1-x2-val_86, i.e. values are in range(1,90,5). Likewise I have files in directory b.
I want to use my python script to access files in a and b to perform iterative operations on .dat files. My present code works only if I keep files of directory a or b in current directory. For example, my script uses following function.
def get_info(test):
my_dict = {'test':test}
c = []
for i in range(1,90,5):
x_val = 'x_val_'+test+'-val_'+str(i)
y_val = 'y_val_'+test+'-val_'+str(i)
my_dict[x_val],my_dict[y_val]= np.loadtxt(test+'-val_'+str(i)+'.dat'
,usecols= (1,2),unpack=True)
dw = compute_yy(my_dict[x_val],my_dict[y_val],test)
c.append(dw)
my_dict.update({test+'_c'+:np.array(c)})
return my_dict
I call get_info() by using following:
tests = ['x1-x1', 'x1-x2']
new_dict = {}
for i in tests:
new_dict.update({i:get_info(i)})
How can I use my code to access files in either directory a and/or b? I know its about providing correct path, but I am unsure how can I do so. One way I thought is following;
ext = '.dat'
for files in os.listdir(path_to_dir):
if files.endswith(ext):
print(files) # do operations
Alternative could be to make use of os.path.join(). However, I am unable to solve it such that I can use same python script (with minimum changes perhaps) that can use files and iterate on them which are in subfolders a and b. Thanks for your feedback in advance!
If you want to run get_info() on every folder separatelly then you have two methods:
First: described by #medium-dimensional in comment
You can use os.chdir(folder) to change Current Working Directory. And then code will run with files in this folder
You can see current working directory with print( os.getcwd() )
os.chdir("a")
get_info(i)
os.chdir("..") # move back to parent folder
os.chdir("b")
get_info(i)
os.chdir("..") # move back to parent folder
chdir() (similar to command cd in console) can use relative path (r"a") full path (r"C:\full\path\to\a") and .. to move to parent folder (r"a\..\b")
If files can be in nested folders then .. may not go back you can use getcwd()
cwd = os.getcwd()
os.chdir("folder1/folder2/a")
get_info(i)
os.chdir(cwd) # move back to previous folder
os.chdir("folder1/folder2/b")
get_info(i)
os.chdir(cwd) # move back to previous folder
(BTW: in console on Linux you can use cd - to move back to previous folder)
Second: use folder when you open file
Every command which gets filename can also get path with folder\filename (it can be relative path, full path, and path with ..) like
r"a\filename.dat"
r"C:\full\path\to\b\filename.dat"
r"a\..\b\filename.dat"
So you could define function with extra option folder
def get_info(text, folder):
and use this folder when you read file
loadtxt(folder + r'\' + test+'-val_'+str(i)+'.dat', ...)
or more readable with f-string
loadtxt(rf'{folder}\{test}-val_{i}.dat', ...)
And later you run it as
get_info(i, "a")
get_info(i, "b")

Python | os.path.join() method

I need help with the following line of code I found in GitHub:
Land Use Land Cover
DATA_FOLDER = os.path.join('..', '..', 'example_data')
I don't know what to put between '.', plus I only downloaded svn_buffered.geojson file.
and this is its current directory:
C:\Users\ASUS\Desktop\PFE-Master\Code
I don't get why do I need to concatenate several paths.
This is the full code:
# Folder where data for running the notebook is stored
DATA_FOLDER = os.path.join('..', '..', 'example_data')
# Load geojson file
country = gpd.read_file(os.path.join(DATA_FOLDER, 'svn_buffered.geojson'))
# Convert CRS to UTM_33N
country_crs = CRS.UTM_33N
country = country.to_crs(crs=country_crs.pyproj_crs())
# Get the country's shape in polygon format
country_shape = country.geometry.tolist()[-1]
# Plot country
country.plot()
plt.axis('off');
# Print size
print('Dimension of the area is {0:.0f} x {1:.0f} m2'.format(country_shape.bounds[2] - country_shape.bounds[0],
country_shape.bounds[3] - country_shape.bounds[1]))```
The script you linked is SI_LULC_pipeline.ipynb and it sits in the project at eo-learn/examples/land-cover-map/SI_LULC_pipeline.ipynb.
Since it is trying to access data in eo-learn/example_data/, to get to the data from the working directory of the script (which apparently is the folder it sits in), it would need to access ../../example_data on almost every OS in the world and the web or ..\..\example_data on Windows.
To avoid using one OS convention or the other, the author of the script has kept it clean and calls os.path.join('..', '..', 'example_data') instead, which leaves it up to Python to decide whether to use '/' or '\' to separate the parts of the path (or whatever the symbol is on the OS it runs on).
In case the '..' itself confuses you: .. means 'the parent directory of the current directory'. Any path either starts in the root (if it begins with \ or /) or in the current working directory of the script. To get access to a directory relative to the current working directory, but via a parent directory, you use ... Similarly, . refers to the current working directory and you can use that at the start of a path to make it explicitly relative to the working directory.
Note how https://github.com/sentinel-hub/eo-learn/blob/master/example_data/svn_buffered.geojson sits in master/example_data/ - compare that to the path the script itself sits in master/examples/land-cover-map. To get from the script to the data, you need to go to the parent folder, then to the parent folder again and then into example_data.

Python | Moving specific Files in User created Folder

I wrote a short script, where I want to moves all .CR2 (in the next step I want to choose between the first the first 2 or 6 files) Files to a Folder, which has been created before as raw_input.
import os
from os import path
import shutil
import itertools
proname = raw_input("Please Name the Productfolder: ")
path = "/Volumes/01_Produktfotos/_2020-01-JANUAR/"
os.mkdir(proname)
os.chdir(proname)
os.makedirs('_final')
os.makedirs('_images')
os.makedirs('_psd')
sourcepath = '/Volumes/01_Produktfotos/_2020-01-JANUAR/03.01/'
sourcefiles = os.listdir(sourcepath)
destinationpath = '/Volumes/01_Produktfotos/_2020-01-JANUAR/03.01/%proname/_images/'
for file in sourcefiles:
if file.endswith('.CR2'):
shutil.move(os.path.join(sourcepath,file), os.path.join(destinationpath,file))
At the moment, the script creates the user specific Folder (proname) and generates the subfolder _images, _final & _psd inside of it.
My Problem is that it doesn't moves the files from the top folder in the user created folder.
The Perfect Result would be if
I can choose a Productfolder Name
It creates inside of the Folder the subfolder _images, _final & _psd
I can choose if I want the first 2-6 .CR2 Files inside of the Subfolder _images of the created Productfolder
The Script is running till there are no .CR2 Files left
Any help or hints are welcome (:
Thx in advance
As in doc, dst is a directory, not a file.
shutil.move(src, dst) Recursively move a file or directory (src) to
another location (dst). If the destination is an existing directory, then src is moved inside that directory. If the destination already exists but is not a directory, it may be overwritten depending on os.rename() semantics.
# Before:
shutil.move(os.path.join(sourcepath,file), os.path.join(destinationpath,file))
# After:
shutil.move(os.path.join(sourcepath,file), destinationpath))
will work.
The following change solved the problem, with moving .CR2 Files in the specific proname Folder:
destinationpath = os.path.join('/Volumes/01_Produktfotos/_2020-01-JANUAR/03.01/', proname, '_images')
Now I'm in the next step, where not all .CR2 files should be moved. Just the first 2 or 6 files.

Script to rename files in folder to match names of files in another folder

I need to do a batch rename given the following scenario:
I have a bunch of files in Folder A
A bunch of files in Folder B.
The files in Folder A are all ".doc",
the files in Folder B are all ".jpg".
The files in Folder A are named "A0001.doc"
The files in Folder B are named "A0001johnsmith.jpg"
I want to merge the folders, and rename the files in Folder A so that they append the name portion of the matching file in Folder B.
Example:
Before:
FOLDER A: Folder B:
A0001.doc A0001johnsmith.jpg
After:
Folder C:
A0001johnsmith.doc
A0001johnsmith.jpg
I have seen some batch renaming scripts, but the only difference is that i need to assign a variable to contain the name portion so I can append it to the end of the corresponding file in Folder A.
I figure that the best way to do it would be to do a simple python script that would do a recursive loop, working on each item in the folder as follows:
Parse filename of A0001.doc
Match string to filenames in Folder B
Take the portion following the string that matched but before the "." and assign variable
Take the original string A0001 and append the variable containing the name element and rename it
Copy both files to Folder C (non-destructive, in case of errors etc)
I was thinking of using python for this, but I could use some help with syntax and such. I only know a little bit using the base python library, and I am guessing I would be importing libraries such as "OS", and maybe "SYS". I have never used them before, any help would be appreciated. I am also open to using a windows batch script or even powershell. Any input is helpful.
This is Powershell since you said you would use that.
Please note that I HAVE NOT TESTED THIS. I don't have access to a Windows machine right now so I can't test it. I'm basing this off of memory, but I think it's mostly correct.
foreach($aFile in ls "/path/to/FolderA")
{
$matchString = $aFile.Name.Split("."}[0]
$bFile = $(ls "/path/to/FolderB" |? { $_.Name -Match $matchString })[0]
$addString = $bFile.Name.Split(".")[0].Replace($matchString, "")
cp $aFile ("/path/to/FolderC/" + $matchString + $addString + ".doc")
cp $bFile "/path/to/FolderC"
}
This makes a lot of assumptions about the name structure. For example, I assumed the string to add doesn't appear in the common filename strings.
It is very simple with a plain batch script.
#echo off
for %%A in ("folderA\*.doc") do (
for %%B in ("folderB\%%~nA*.jpg") do (
copy "%%A" "folderC\%%~nB.doc"
copy "%%B" "folderC"
)
)
I haven't added any error checking.
You could have problems if you have a file like "A1.doc" matching multiple files like "A1file1.jpg" and "A10file2.jpg".
As long as the .doc files have fixed width names, and there exists a .jpg for every .doc, then I think the code should work.
Obviously more code could be added to handle various scenarios and error conditions.

Categories

Resources