I am Trying to add a custom path filed in my GUI but the problem is that when i use the command
cmds.fileDialog2(filemode=3,dialogStyle =1)
i get a file path like
C:\Users\anoorani\Desktop\Test
However Maya only seems to be reading paths like
C:/Users/anoorani/Desktop/Test
The backticks seem to be a problem
is there a way to replace "\" with "/" in python maya.....?
Acording to #ArgiriKotsaris note, you can use os.path.normpath(path):
Normalize a pathname by collapsing redundant separators and up-level references.
So that A//B, A/B/, A/./B and A/foo/../B all become A/B.
This string manipulation may change the meaning of a path that contains symbolic links.
On Windows, it converts forward slashes to backward slashes.
So your code be:
import maya.cmds as cmds
import os
path = cmds.fileDialog2(fm=3,dialogStyle =1)
path = path and os.path.normpath(path[0])
Or if you want to always using forward slashes, then no needs to os module and change last line to:
path = path and path[0].replace('\\', '/')
Note that name of file mode argument for fileDialog2 is fileMode or fm and not filemode.
Also fileDialog2 return a list of paths or None.
Related
I have a given file path. For example, "C:\Users\cobyk\Downloads\GrassyPath.jpg". I would like to pull in a separate string, the image file name.
I'm assuming the best way to do that is to start from the back end of the string, find the final slash and then take the characters following that slash. Is there a method to do this already or will I have search through the string via a for loop, find the last slash myself, and then do the transferring manually?
The pathlib module makes it very easy to access individual parts of a file path like the final path component:
from pathlib import Path
image_path = Path(r"C:\Users\cobyk\Downloads\GrassyPath.jpg")
print(image_path.name) # -> GrassyPath.jpg
You can certainly search manually as you've suggested. However, the Python standard library already has, as you suspected, a function which does this for you.
import os
file_name = os.path.basename(r'C:\Users\cobyk\Downloads\GrassyPath.jpg')
I am creating a format string that is different based on class, that is used to generate a filename by a generic class method. I'm using the Python 3.4+ pathlib.Path module for object-oriented file I/O.
In building this string, the path separator is missing, and rather than just put the windows version in, I want to add a platform independent file separator.
I searched the pathlib docs, and answers here about this, but all the examples assume I'm building a Path object, not a string. The pathlib functions will add the correct separator in any string outputs, but those are actual paths - so it won't work.
Besides something hacky like writing a string and parsing it to figure out what the separator is, is there a way to directly get the current, correct file separator string?
Prefer an answer using pathlib.Path, rather than os or shutil packages.
Here's what the code looks like:
In the constructor:
self.outputdir = Path('drive:\\dir\\file')
self.indiv_fileformatstr = str(self.outputdir) + '{}_new.m'
In the final method used:
indiv_filename = Path(self.indiv_fileformatstr.format(topic))
This leaves out the file separator
There is nothing public in the pathlib module providing the character used by the operating system to separate pathname components. If you really need it, import os and use os.sep.
But you likely don't need it in the first place - it's missing the point of pathlib if you convert to strings in order to join a filename. In typical usage, the separator string itself isn't used for concatenating path components because pathlib overrides division operators (__truediv__ and __rtruediv__) for this purpose. Similarly, it's not needed for splitting due to methods such as Path.parts.
Instead of:
self.indiv_fileformatstr = str(self.outputdir) + '{}_new.m'
You would usually do something like:
self.indiv_fileformatpath = self.outputdir / '{}_new.m'
self.indiv_fileformatstr = str(self.indiv_fileformatpath)
The platform-independent separator is in pathlib.os.sep
Solution using wim's answer
Based on wim's answer, the following works great:
Save the format string in the Path object
When needing to substitute into the templated filename in the future, just use str(path_object) to get the string back out.
import pathlib
# Start with following, with self.outputdir as pathlib.Path object
outputdir = 'c:\\myfolder'
file_template_path = outputdir / '{}_new.m'
# Then to make the final file object later (i.e. in a child class, etc.)
base_filename_string = 'myfile'
new_file = pathlib.Path(str(file_template).format(base_filename_string))
This creates:
pathlib.Path("c:\\myfolder\myfile_new.m")
Creating the template with prefix/postfix/etc.
If you need to apply other variables, you can use 2 levels of formatting to apply specialized prefixes/postfixes, etc., then store the final template in a Path object, as shown above.
When creating 2 levels of formatting, use double brackets where the first level formatter should just create a single bracket and not try to interpret a tag. i.e. {{basename}} becomes just {basename} without any variable substitution.
prefix = 'new_'
postfix = '_1'
ext = 'txt'
file_template_path = outputdir / f'{prefix}{{}}{postfix}.{ext}'
which becomes a path object with the following string:
$ file_template_path
pathlib.Path("c:\\myfolder\new_{}_1.txt")
I use the following python code to get list of jpg files in nested subdirectories which are in parent directory.
import glob2,os
all_header_files = glob2.glob(os.path.join('Path/to/parent/directory','/**/*.jpg'))
However, I get nothing but when I cd into the parent directory and I use the following python code then I get the list of jpeg files.
import glob2
all_header_files = glob2.glob('./**/*.jpg')
How can I get the result with the absolute path?(first version)
You have an extra slash.
The os.path.join will insert the filepath separators for you, so you should think of it as this to get the correct directory
join('Path/to/parent directory' , '**/*.jpg')
Even more accurately,
parent = os.path.join('Path', 'to', 'parent directory')
os.path.join(parent, '**/*.jpg')
If you are trying to use your Home directory, see os.path.expanduser
In [10]: import os, glob
In [11]: glob.glob(os.path.join('~', 'Downloads', "**/*.sh"))
Out[11]: []
In [12]: glob.glob(os.path.expanduser(os.path.join('~', 'Downloads', "**/*.sh")))
Out[12]:
['/Users/name/Downloads/dir/script.sh']
You should not join with the trailing slash as you'll end up with the root. You can debug by printing out the resulting path before passing it to glob.
Try to change your code like this (note the dot):
import glob2,os
all_header_files = glob2.glob(os.path.join('Path/to/parent directory','./**/*.jpg'))
os.path.join() joins paths in an intelligent way.
os.path.join('Path/to/anything','/**/*.jpg'))
resolves to '/**/*.jpg' since '/**/*.jpg' is any path, ever.
Change the '/**/*.jpg' to '**/*.jpg' and it should work.
In cases like this, I recommend to always try out the result of a certain function within the python command line. At least, this is how I found out the issue here.
The problem with the code you have posted lies in the use of os.path.join.
In the documentation it says for os.path.join(path, *paths):
If a component is an absolute path, all previous components are thrown away and joining continues from the absolute path component.
In your case, the component /**/*.jpg is an absolute path, as it starts with a /. Consequently your initial input /Path/to/parent directory is being truncated by the call to the join function. (https://docs.python.org/3.5/library/os.path.html#os.path.join)
I have locally tested the joining part with python3 and for me it is the case, that using os.path.join(any_path, "/**/*.pdf") returns the string '/**/*.pdf'.
The fix for this error is:
import glob2,os
all_header_files = glob2.glob(os.path.join('Path/to/parent directory','**/*.jpg'))
This returns the path 'Path/to/parent directory/**/*.jpg'
The following line, unless I'm mistaken, will grab the absolute path to your directory so you can access files
PATH = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0])))
This is what I've been using typically access files in my current directory when I need to use images etc in the programs i've been writing.
Now, say I do the following since I'm using windows to access a specific image in the directory
image = PATH + "\\" + "some_image.gif"
This is where my question lies, this works on windows, but if I remember correctly "\\" is for windows and this will not work on other OS? I cannot directly test this myself as I don't have other operating systems or I wouldn't have bothered posting. As far as I can tell from where I've looked this isn't mentioned in the documentation.
If this is indeed the case is there a way around this?
Yes, '\\' is just for Windows. You can use os.sep, which will be '\\' on Windows, ':' on classic Mac, '/' on almost everything else, or whatever is appropriate for the current platform.
You can usually get away with using '/'. Nobody's likely to be running your program on anything but Windows or Unix. And Windows will accept '/' pathnames in most cases. But there are many Windows command-line tools that will confuse your path for a flag if it starts with /, and some even if you have a / in the middle, and if you're using \\.\ paths, a / is treated like a regular character rather than a separator, and so on. So you're better off not doing that.
The simple thing to do is just use os.path.join:
image = os.path.join(PATH, "some_image.gif")
As a side note, in your first line, you're already using join—but you don't need it there:
PATH = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0])))
It's perfectly legal to call join with only one argument like this, but also perfectly useless; you just join the one thing with nothing; you will get back exactly what you passed in. Just do this:
PATH = os.path.abspath(os.path.dirname(sys.argv[0]))
One last thing: If you're on Python 3.4+, you may want to consider using pathlib instead of os.path:
PATH = Path(sys.argv[0]).parent.resolve()
image = PATH / "some_image.gif"
Use os.path.join instead of "\\":
os.path.join(PATH, "some_image.gif")
The function will join intelligently the different parts of the path.
PATH = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0])))
image = os.path.join(PATH, "some_image.gif")
os.path.join will intelligently join the arguments using os.sep which uses the OS file separator for you.
I have a requirement for adding and splitting path in my app.I want to work with this app on windows and linux.Here is my code to add paths
path = os.path.join(dir0,dir1,dir2,fn)
But when i am splitting with slashes i am facing problems .Because
the path in windows like:
dir0\dir1\dir2\fn
the path in linux like
dir0/dir1/dir2/fn
Now how can i split the path with single code(with out changing the code while using other platform/platform independent)
You can use os.sep
just
import os
path_string.split(os.sep)
For more info, look the doc
os.path.join(path1[, path2[, ...]])
Join one or more path components intelligently. If any component is an absolute path, all previous components (on Windows, including the previous drive letter, if there was one) are thrown away, and joining continues. The return value is the concatenation of path1, and optionally path2, etc., with exactly one directory separator (os.sep) following each non-empty part except the last. (This means that an empty last part will result in a path that ends with a separator.) Note that on Windows, since there is a current directory for each drive, os.path.join("c:", "foo") represents a path relative to the current directory on drive C: (c:foo), not c:\foo.
Use os.path.split. It is a system independent way to split paths. Note that this only splits into (head, tail). To get all the individual parts, you need to recursively split head or use str.split using os.path.sep as the separator.