i have this structure in my code.
app
src
script.py
data
data.ptk
i need to open the file "data.ptk" from "scrip.py", using os.path i'm able to extract the script path.
my_path = os.path.abspath(os.path.dirname(__file__))
But flowing the structure i need to go back 2 directories and then enter the "data" directory to open the file.
The easy way would be to decompose the string my_path with a split("/"), remove the last 2 words and add "data" ...
But I do not think it's the right way
The script.py need to be independent of the OS, that is the reason i'm not able to "hard code" the directory where de pkl file is placed
Any suggestions? thanks.
To elaborate on my comment more, you can see the documentation for pathlib here: https://docs.python.org/3/library/pathlib.html?highlight=pathlib#module-pathlib. It is a stock part of python3 (not sure about python2). I think the following would work:
from pathlib import Path
scriptPath = Path(__file__).absolute() # the absolute() is not strictly necessary
srcPath = scriptPath.parent
appPath = srcPath.parent
commonDirectory = appPath.parent # this could have been shortened with scriptPath.parent.parent.parent
dataPath = commonDirectory / 'data'
dtkFile = dataPath / 'data.ptk'
Related
I'm trying to move files from one directory to another using Python - spyder.
My file extension is *.OD which python does not support or read.
I have tried using the wildcard and leaving out the file extension (which does not work). Another file extension cannot be used for this particular file.
Moving python supported extensions such as .txt and .csv works fine.
import shutil
source = '//Original_Filepath/Extract*.od'
target = '//NewFilePath/Extract_*.od'
shutil.copy(source, target)
There are no errors, it just doesn't move/copy the file.
Thanks,
There are a couple of basic mistakes with how you're trying to copy the files. With shutil.copy you should not specify a glob, but instead the exact source and destination.
If instead you want to copy a set of files from one directory to another and (presuming the added underscore isn't a mistake) change the target, then you should try using pathlib in combination with shutil (and re if needed).
pathlib - Object-oriented filesystem paths
Try adapting this:
import pathlib
import shutil
import re
source = pathlib.Path('//Original_Filepath') # pathlib takes care of end slash
source_glob = 'Extract*.od'
target = pathlib.Path('//NewFilePath')
for filename in source.glob(source_glob):
# filename here is a Path object as well
glob_match = re.match(r'Extract(.*)\.od', filename.stem).group(1)
new_filename = "Extract_{}.od".format(glob_match)
shutil.copy(str(filename), str(target / new_filename)) # `/` will create new Path
If you're not interested in editing the target nor using any other advanced feature that pathlib provides then see Xukrao's comment.
Thank you all for your help. Much appreciated! :)
I was also able to copy the file with the below as well (a bit simpler).
I left out the * and used a date string instead.
import shutil
from datetime import datetime
now = datetime.now()
Org_from=os.path.abspath('//Original FilePath')
New_to=os.path.abspath('//New Path')
shutil.copy(os.path.join(org_from, 'File_' + now.strftime("%Y%m%d") + '.od'), os.path.join(New_to, 'File_' + now.strftime("%Y%m%d") + '.od'))
Cheers,
Jen
When I try to parse a xml file in a sub directory I get a FileNotFoundError. When I put the file next to the script it can parse it fine. But why?
#!/usr/bin/env python3
import os
import xml.etree.ElementTree as ET
script_path = os.path.dirname(os.path.realpath(__file__))
path_to_file = os.path.join(script_path, '/test', 'file.xml')
# works
tree = ET.parse('file.xml')
# Throws file not found error
tree = ET.parse(path_to_file)
Try the easiest possible way of debugging by printing the value of path_to_file.
os.path.join() is used so you don't have to specify the (os-specific) path separator character for the path it constructs, which means you don't need to (shouldn't) specify them.
You are over-specifying the path separator on the test part - change:
path_to_file = os.path.join(script_path, '/test', 'file.xml')
to
path_to_file = os.path.join(script_path, 'test', 'file.xml')
Try writing '/test' without the leading slash.
path_to_file = os.path.join(script_path, 'test', 'file.xml')
I am posting the answer myself because although the answers solve the problem, they do not give the correct reason why their code works and mine doesn't.
The significant issue with my code is, that the line
path_to_file = os.path.join(script_path, '/test', 'file.xml')
# Expected value of path_to_file:
# /path/to/script/test/file.xml
# Output of print(path_to_file):
# /test/file.xml
contains the absolute path /test instead of the relative path ./test or as pointed out earlier the better way test.
The result is that with /test, the resulting path will not contain the contents of script_path.
The previous answers might help in cases where you go down one directory, but don't cover cases like
path_to_file = os.path.join(script_path, 'test/subdir', 'file.xml')
Where you might find the / useful. I think one can trust os.path.join() to take care of those platform specific directories. Please let me know if you don't agree with me one this.
I'm trying to use relative paths in Python, and I want to put my csv files in a separate folder from my python code.
My python program is in the following folder:
G:\projects\code
I want to read this file which is one level up:
G:\projects\data\sales.csv
How do I specify a path using pathlib that is one level up from my current working folder? I don't want to change the current working folder.
I tried this:
from pathlib import Path
file = Path.cwd() /'..'/'data'/'sales.csv'
But now the 'file' variable equals this:
'G:/projects/code/../data/sales.csv'
I read through the docs and either it isn't explained there or I'm just missing it.
Although it's not a problem that your path includes '..' (you can still use this path to open files, etc. in Python), you can normalize the path using resolve():
from pathlib import Path
path = Path.cwd() / '..' / 'data' / 'sales.csv'
print(path) # WindowsPath('G:/projects/code/../data/sales.csv')
print(path.resolve()) # WindowsPath('G:/projects/data/sales.csv')
NB: I personally would name a variable that contains a path path, not file. So you could later on do file = open(path).
print(
Path(__file__).parent, # the folder
Path(__file__).parent.parent, # the folder's parent
sep='\n'
)
print(
Path(
Path(__file__).parent.parent, 'hello.py'
)
)
results in
C:\Users\isik\Desktop\Python\MessAround\project\module
C:\Users\isik\Desktop\Python\MessAround\project
C:\Users\isik\Desktop\Python\MessAround\project\hello.py
with this file structure
-project
-module
-__init__.py
-hello.py
-__init__.py
while the code is located inside project.module.__init__.py
Do you mean "read my csv files"?
The import keyword has a different meaning in Python (you import only other Python modules).
In any case, in order to read a file located one folder above your Python file, you can use this:
import os
filePath = os.path.dirname(__file__)+'/../'+fileName
fileDesc = open(filePath)
fileData = fileDesc.read()
fileDesc.close()
...
here is an example I used:
import json
from pathlib import Path
def read_files(folder_name, file_name):
base_path = Path.cwd().joinpath('configs','resources')
path = base_path.joinpath(folder_name,file_name)
open_file = open(path,'r')
return json.load(open_file.read())
This is pretty old, but I happened on it looking for something else.
Oddly you never got a direct, obvious, answer -- you want the parent property:
from pathlib import Path
file = Path.cwd().parent / 'data' / 'sales.csv'
Note that some of the answers that say you want __file__ rather than the current working directory may be correct (depending on your use case), in which case it's:
from pathlib import Path
file = Path(__file__).parent.parent / 'data' / 'sales.csv'
(parent of the python file is the code dir, parent of that is the projects dir.
However, It's not great practice to refer to your data by its relative path to your code -- I think using the cwd is a better option -- though what you should do is pass the path to the data in to the script via sys.argv.
I am trying to access a text file in the parent directory,
Eg : python script is in codeSrc & the text file is in mainFolder.
script path:
G:\mainFolder\codeSrc\fun.py
desired file path:
G:\mainFolder\foo.txt
I am currently using this syntax with python 2.7x,
import os
filename = os.path.dirname(os.getcwd())+"\\foo.txt"
Although this works fine, is there a better (prettier :P) way to do this?
While your example works, it is maybe not the nicest, neither is mine, probably. Anyhow, os.path.dirname() is probably meant for strings where the final part is already a filename. It uses os.path.split(), which provides an empty string if the path end with a slash. So this potentially can go wrong. Moreover, as you are already using os.path, I'd also use it to join paths, which then becomes even platform independent. I'd write
os.path.join( os.getcwd(), '..', 'foo.txt' )
...and concerning the readability of the code, here (as in the post using the environ module) it becomes evident immediately that you go one level up.
To get a path to a file in the parent directory of the current script you can do:
import os
file_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'foo.txt')
You can try this
import environ
environ.Path() - 1 + 'foo.txt'
to get the parent dir the below code will help you:
import os
os.path.abspath(os.path.join('..', os.getcwd()))
I'm new to Python and really want this command to work so I have been looking around on google but I still can't find any solution. I'm trying to make a script that deletes a folder inside the folder my Blender game are inside so i have been trying out those commands:
import shutil
from bge import logic
path = bge.logic.expandPath("//")
shutil.rmtree.path+("/killme") # remove dir and all contains
The Folder i want to delete is called "killme" and I know you can just do: shutil.rmtree(Path)
but I want the path to start at the folder that the game is in and not the full C:/programs/blabla/blabla/test/killme path.
Happy if someone could explain.
I think you are using shutil.rmtree command in wrong way. You may use the following.
shutil.rmtree(path+"/killme")
Look at the reference https://docs.python.org/3/library/shutil.html#shutil.rmtree
Syntax: shutil.rmtree(path, ignore_errors=False, onerror=None)
Assuming that your current project directory is 'test'. Then, your code will look like the follwing:
import shutil
from bge import logic
path = os.getcwd() # C:/programs/blabla/blabla/test/
shutil.rmtree(path+"/killme") # remove dir and all contains
NOTE: It will fail if the files are read only in the folder.
Hope it helps!
What you could do is set a base path like
basePath = "/bla_bla/"
and then append the path and use something like:
shutil.rmtree(basePath+yourGamePath)
If you are executing the python as a standalone script that is inside the desired folder, you can do the following:
#!/usr/bin/env_python
import os
cwd = os.getcwd()
shutil.rmtree(cwd)
Hope my answer was helpful
The best thing you could do is use the os library.
Then with the os.path function you can list all the directories and filenames and hence can delete/modify the required folders while extractring the name of folders in the same way you want.
for root, dirnames, files in os.walk("issues"):
for name in dirnames:
for filename in files:
*what you want*