OS Independant Pathing? (Once and for all!)

Hello All,

Every single script I have written that involves pathing to the local file system always ends up broken at some point. This is because behind the scenes Blender or Python mangles my valid string intentions for paths into some kind of gobbly gook that is not recognized as a path any more.

For instance, this morning on my Window machine I type:

import os

COMPILER_PATH = "C:\Program Files\3Delight\bin"
if os.path.exists(COMPILER_PATH):
    print ("valid path on Windows")
    print ("invalid path on Windows")

COMPILER_PATH is the string that was returned to me by Blender when I browsed to using a FILE_PATH type GUI input field. Python, of course, sees this as invalid. See image, I now have a ‘heart’ icon as part of my string path (WTF).

I am tired of constantly writing path fixup code for various cases and OS’s. I would like a solution for pathing that works for every OS all the time and never breaks.

Can someone show me the correct way to process files and folder paths so it works for all OS’s and can be used with the subprocess command? I want to launch other executables with parameters.

Since the character used for window’s path separator is also the character used to escape special characters, you might have to either use r"rawstrings" or double up on the number of slashes in a windows path. In other words, escape your backslashes with more backslashes, or else the backslashes will escape something unintended.

In your example above, \3 became a heart, and \b backspaced over the t of 3Delight\bin , turning it to 3Delighin.

A good os-agnostic way to build paths is to use os.path.join. For dissecting paths, various other functions of the os.path module such as basename, dirname, realpath …

I’m sorry, I don’t really have a good answer - these are just a few things that come to mind.

Thanks for the reply. I am taking the approach of managing all aspects of the file path via os.path. But I still am not sure about file extensions for programs.

If I have a render engine like Pixie or 3Delight that have a set of tools that are cross platform how do I handle the launching of such a program on various OS’s? 3Delight, for example, will have a program called ‘shader_info.exe’ on Windows and ‘shader_info.app’ on OSX. I am not sure what Unix/Linux uses.

Is there a way to launch a program, via python, without specifying it’s extension?

Right now, I have…

        # Construct an alternate shell command based upon OS type?
        if sys.platform.startswith('darwin'):
            # Just guessing here...
            program_extension = ".app"
        elif sys.platform.startswith('win'):
            program_extension = ".exe"
        elif sys.platform.startswith('linux'):
            # Just guessing here...
            program_extension = ".so"

As dustractor noted, the problem is that you have put your string directly into your Python code and Python does some processing on the strings.

One way would be to create a simple CSV file storing the property name + value. Something like:

COMPILER_PATH,C:\Program Files\3Delight\bin

Then you load that into a dictionary like so:

properties = {}
with open('properties.txt', 'r') as input:
  for line in input:
    tokens = line.split(',')
    properties[tokens[0]] = tokens[1]

Then you can access your value like so:

if os.path.exists(properties['COMPILER_PATH']):
  # do stuff

The ‘advantage’ here is that since Python is just reading the contents of a text file, the path separators don’t get processed like a string in Python code.

Other options are to always use raw strings for paths if you really want to hardcode those paths into your source code.

Thanks for the tips. I am giving up on any hard coding of strings. All sources I can find say there is not way to avoid the ESCAPE character in strings so I am giving up. I thought there might be a problem with user input via browsing but after a bit of testing it seems I can type the exact path into a UI FILE_PATH text field (instead of hard code it) and it works fine.

To have python not escape, use raw strings:

Python 3.4.1 (v3.4.1:c0e311e010fc, May 18 2014, 10:45:13) [MSC v.1600 64 bit (AMD64)] on win32Type "copyright", "credits" or "license()" for more information.
>>> "C:\Program Files\3Delight\bin"
'C:\\Program Files\x03Delight\x08in'
>>> r"C:\Program Files\3Delight\bin"
'C:\\Program Files\\3Delight\\bin'

Just prepend the ‘r’ to the beginning of the quote. Secondly I use slash instead of backslash on Windows, unless a special use requires it.

COMPILER_PATH = r"C:\Program Files\3Delight\bin"
COMPILER_PATH = “C:/Program Files/3Delight/bin”