How do I best identify if a String is a Windows path or a UNIX style path?
Example Strings:
some_path = '/Volumes/network-drive/file.txt'
or
some_path = 'Z:\\network-drive\\file.txt'
One way is to check which slashes the String contains:
if '/' in some_path:
# do something with UNIX Style Path
elif '\\' in some_path:
# do something else with Windows Path
Is there a better way to do this? I couldn't find suited methods in os.path or pathlib. BTW, assume that the path string will come from another system so it doesn't help to check on which OS my code runs on.
Related
How do I convert a path like r'C:\Users\usern\Documents\file.txt' into a list like ['C:', 'Users', 'usern', 'Documents', 'file.txt']? I'd like it to work cross-platform, on Windows regardless on whether the path is given with forward slashes or backslashes or with a mixture of both, and regardless on whether the input string ends with a slash or not (i.e., no empty strings at the end for inputs like 'C:\\Users\\usern\\Documents\\').
To my best knowledge, the following should work on Windows, Mac and Linux:
import sys
def path_to_list(s):
if sys.platform == 'win32':
return s.replace('\\', '/').rstrip('/').split('/')
else:
return s.rstrip('/').split('/')
but I'm not sure if that works on other platforms where Python can be run, nor if this solution is very Pythonic for even these common platforms.
Problems could arise at least in the following cases:
if some platform allows an empty string to be a filename or a folder name,
if there exists a platform other than Windows which doesn't allow backslashes in filenames
if there exists any platform that does not allow the forward slash (/) as file-folder separator
if there exists any platform that allows characters other than the backslash (\) or forward slash (/) as file-folder separator
but I'm not sure if platforms like those exist and if so, does Python even run on them (if it doesn't no problem would be caused then)?
By the way, you cannot use if '\\' in __file__: ... (as a replacement for if sys.platform == 'win32' in the code block) to check if backslashes are allowed because, for some reason, __file__ returns the path to the current script with forward slashes even on Windows. And it probably wouldn't be a good way to do this even if this wasn't the case.
You could make use of pathlib, specifically the parts method, like so:
from pathlib import Path
myPath = Path(r"C:\Program Files\CMake\bin\cmake.exe")
print(list(myPath.parts))
Returns ['C:\\', 'Program Files', 'CMake', 'bin', 'cmake.exe']
Edit
You can join the path back together like so
newPath = Path(*myPath.parts)
print(newPath)
Returns C:\Program Files\CMake\bin\cmake.exe
Problem:
I'm having different behavior for Windows and Linux in the following case.
import os
path = '..\\file.hdf'
norm_path = os.path.normpath(path)
splitted_path = os.path.split(norm_path)
print(splitted_path)
Behavior
On Windows I get ('', 'file.hdf')
On Linux I get ('', '..\\file.hdf')
Question
Is there a better/specific way to use the os.path for this?
Workaround
Ok, it's easily fixed with norm_path.split('\\'), but that's not dynamic at all.
On Linux, paths are separated with a forward slash. If you want a platform-independent approach, I suggest using os.sep instead of backslash:
import os
path = '..' + os.sep + 'file.hdf'
norm_path = os.path.normpath(path)
split_path = os.path.split(norm_path)
print(split_path)
In Linux \ is NOT a path separator. Therefore, your ..\\file.hdf means "a file named file.hdf in the parent directory of the current directory" on Windows, but simply "a file named ..\file.hdf in current directory" on Linux. I suggest using pathlib module instead of os.path:
import pathlib
norm_path = pathlib.PureWindowsPath('..\\file.hdf')
split_path = list(norm_path.parts)
# ['..', 'file.hdf'] both on Linux and Windows
replace \\ with /
Windows can handle / as path separator.
Linux can't handle \\
So use / for any code you want to be able to be running on Linux and Windows
Or do it the really clean way by using os.sep as #snibbets suggests.
In that case I'd use os.sep.join('..', 'file.hdf')
I have a few questions regarding to the path in Python using os module:
(1) If using os module, is there any difference between \ and / in regards to the absolute path of a file?
For examples:
import os
example_path_1 = "C:\abc\def"
example_path_2 = "C:/abc/def"
a. Can os.system(example_path_1) and os.system(example_path_2) both work?
b. Can os.mkdir(example_path_1) and os.mkdir(example_path_2) both work?
(2) When using the os module in Python, if I'm getting this right, it seems in some situations we have to use /, and the other situations we have to use \. How to tell the difference?
You would be safe with always sticking to forward slashes
example_path = "/c/abc/def"
If you use windows style, you need to escape them or use a raw string
example_path = "C:\\abc\\def"
example_path = r"C:\abc\def"
In general, stick to doing as much as you can in the os.path module, it will handle these OS-specific issues fairly robustly. For example you can pass a path to os.path.normpath and it will normalize your slashes to whatever platform you're on. Similarly building up paths with os.path.join will insert the correct slashes for your system.
Good morning, I can indicate how to enter a path of internal hard disk in python, currently use the statement:
file = GETfile() or 'http://**********'
I would like to put a path to a local file, but it does not work, where am I wrong?
file = GETfile() or 'D:\xxx\xxxx\playlist\playlist.m3u'
\ is a escape character. You have three options.
1) use /. This, as a bonus works for linux as well:
'D:/xxx/xxxx/playlist/playlist.m3u'
2) escape the backslash
'D:\\xxx\\xxxx\\playlist\\playlist.m3u'
3) use raw strings:
r'D:\xxx\xxxx\playlist\playlist.m3u'
A correct answer is already given, but some additional information when working with local drive paths on Windows operating system.
Personally I would go with the r'D:\dir\subdir\filename.ext' format, however the other two methods already mentioned are valid as well.
Furthermore, file operations on Windows are limited by Explorer to a 256 character limit. Longer path names will usually result in an OS error.
However there is a workaround, by pre fixing "\\?\" to a long path.
Example of a path which does not work:
D:\reallyreallyreallyreallyreallylonglonglonglongdir\reallyreallyreallyreallyreallylonglonglonglongdir\reallyreallyreallyreallyreallylonglonglonglongdir\reallyreallyreallyreallyreallylonglonglonglongdir\reallyreallyreallyreallyreallylonglonglonglongdir\reallyreallyreallyreallyreallylonglonglonglongdir\reallyreallyreallyreallyreallylonglonglonglongdir\reallyreallyreallyreallyreallylonglonglonglongdir\filename.ext
Same file path which does work:
\\?\D:\reallyreallyreallyreallyreallylonglonglonglongdir\reallyreallyreallyreallyreallylonglonglonglongdir\reallyreallyreallyreallyreallylonglonglonglongdir\reallyreallyreallyreallyreallylonglonglonglongdir\reallyreallyreallyreallyreallylonglonglonglongdir\reallyreallyreallyreallyreallylonglonglonglongdir\reallyreallyreallyreallyreallylonglonglonglongdir\reallyreallyreallyreallyreallylonglonglonglongdir\filename.ext
so the following code I use to change filenames to include the "\\?\":
import os
import platform
def full_path_windows(filepath):
if platform.system() == 'Windows':
if filepath[1:3] == ':\\':
return u'\\\\?\\' + os.path.normcase(filepath)
return os.path.normcase(filepath)
I use this for every path to file (or directories), it will return the path with a prefix. The path does not need to exist; so you can use this also before you create a file or directory, to ensure you are not running into the Windows Explorer limitations.
HTH
I need to resolve a disparity between the separator that sys.path is providing, and the separator that os.path.join is using.
I mimicked this Esri method (Techniques for sharing Python scripts) to make my script portable. It is being used in Windows for now, but will eventually live on a Linux server; I need to let Python determine the appropriate slash.
What they suggest:
# Get the pathname to this script
scriptPath = sys.path[0]
# Get the pathname to the ToolShare folder
toolSharePath = os.path.dirname(scriptPath)
# Now construct pathname to the ToolData folder
toolDataPath = os.path.join(toolSharePath, "ToolData")
print "ToolData folder: " + toolDataPath
But this outputs ToolData folder: C:/gis\ToolData -- and obviously the mixed slashes aren't going to work.
This Question (mixed slashes with os.path.join on windows) includes the basic approach to a solution:
check your external input (the input you apparently do not control the format of) before putting it in os.path.join. This way you make sure that os.path.join does not make bad decisions based on possibly bad input
However, I'm unsure how to ensure that it will work cross-platform. If I use .replace("/","\\") on the sys.path[0] result, that's great for Windows, but isn't that going to cause the same mixed-slash problem once I transition to Unix?
How about using os.path.normpath()?
>>> import os
>>> os.path.normpath(r'c:\my/path\to/something.py')
'c:\\my\\path\\to\\something.py'
Also worth mentioning: the Windows path API doesn't care whether forward or back slashes are used. Usually it's the fault of program that doesn't handle the slashing properly. For example, in python:
with open(r'c:/path/to/my/file.py') as f:
print f.read()
will work.
After reading the documentation and trying a lot of variations:
The os.path.abspath function can "clean" the slashes, so whichever direction slash sys.path[0] decides to use, the slashes will be replaced with the preferred separator.
scriptPath = sys.path[0]
toolDataPath = os.path.join(scriptPath, "ToolData")
Result: C:/gis\ToolData
scriptPath = sys.path[0]
toolSharePath = os.path.abspath(scriptPath)
# or, in one line: toolSharePath = os.path.abspath(sys.path[0])
toolDataPath = os.path.join(toolSharePath, "ToolData")
Result: C:\gis\ToolData
There is an os.sep character in Python, which stores your OS's preferred folder separating character. Perhaps you could perform a manual string join using that?
On Linux:
>>> import os
>>> os.sep
'/'
https://docs.python.org/2/library/os.html#os.sep