15
$\begingroup$

Functions such as os.path.exists(image.filepath) fail when Blender uses relative paths, This seems to be because Blender uses // prefix for relative paths, unlike the more conventional ./.

How can standard Python filesystem functions be used correctly on Blender paths?

$\endgroup$

2 Answers 2

20
$\begingroup$

The // prefix is Blender specific to denote relative paths used within Blender,

To use Python's filesystem functions you'll have to first expand this using:

eg:

filepath_full = bpy.path.abspath(image.filepath, library=image.library)

Unlike ./, which simply expands the current-working-directory (os.getcwd()), Blender supports library-linked files. This means the directory of the current data-block could be a different path then the currently open Blend file.

If you are operating data which the script created, You can skip passing the library argument.

filepath_full = bpy.path.abspath(image.filepath)

Note that this isn't specific to images, it works for movie-clip, sounds, sequencer and text blocks too.

$\endgroup$
1
  • $\begingroup$ I'm dealing with a different situation, where I just used a StringProperty with the directory setting on to pick out a destination directory. I had one person insisting that there was no need to force an absolute path. Then, tonight, testing my script, it crashed because I had not changed the setting in the file requestor to Absolute Path. This was literally the last bug to stomp out at 2 AM. Thank you - you gave me the answer and it was easy to just wrap bpy.path.abspath() around my StringProperty to always get the full path. Again, thanks! $\endgroup$ Commented Apr 20, 2021 at 7:55
9
$\begingroup$

This may be off topic, but if you encounter the following situation, this may help you.

I was automating the creation of blender files which

  1. Took an existing file,

  2. Replaced some textures, moved stuff around, changed sizes of some objects etc.,

  3. SAVED THE BLENDER FILE TO ANOTHER FOLDER.

I couldn't figure out why in the saved file, all textures had relative paths assigned to them, even though in all possible settings in Blender I set relative paths to False, like the setting User Preferences / File / Save & Load / Relative Paths to [ ] (unchecked) and using bpy.context.user_preferences.filepaths.use_relative_paths = False.

All textures still had their paths in the form '//.../.../...' which was not what I wanted AND those paths were relative TO THE LOCATION OF THE ORIGINAL BLENDER FILE and not relative to the newly saved one.

Then it dawned to me, but this is not documented anywhere, that the problem is not where I had expected it, but rather when the new file is being saved. I used the method bpy.ops.wm.save_as_mainfile() and this method, as it turned out, was the reason. It has an optional argument relative_remap WHICH DEFAULTS TO True and means that THE MOMENT you save your new file, all paths get converted to relative (and relative to the location of the currently open file, not to the location where your new file is being saved to). Hope this saves you some time, it took me hours to figure out.

So, you need

bpy.ops.wm.save_as_mainfile(filepath = YourNewFilePath, relative_remap = False)

$\endgroup$
3
  • 2
    $\begingroup$ Cant upvote this enough. $\endgroup$ Commented May 9, 2019 at 5:05
  • 1
    $\begingroup$ Ditto - this answer saved me. $\endgroup$ Commented Jun 10, 2020 at 4:12
  • $\begingroup$ Nice, so if you want to toggle the checker box in blender 4.x from Preferences >Save & Load > Blender files > Relative Paths just use bpy.context.preferences.filepaths.use_relative_paths = True (or False depending what you want). With blender 3.x bpy.context.user_preferences.filepaths.use_relative_paths = True will do the trick $\endgroup$ Commented Jul 24, 2024 at 20:16

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.