absolute path to a file
Paul St George
email at paulstgeorge.com
Mon Aug 19 16:06:00 EDT 2019
On 19/08/2019 14:16, Cameron Simpson wrote:
> On 19Aug2019 08:52, Paul St George <email at paulstgeorge.com> wrote:
>> On 19/08/2019 01:31, Cameron Simpson wrote:
>>> On 18Aug2019 17:29, Paul St George <email at paulstgeorge.com> wrote:
>>>> On 18/08/2019 02:03, Cameron Simpson wrote:
>>>> 1: Is image01.tif a real existing file when you ran this code?
>>>> Yes. image01.tif is real, existing and apparent.
>>> But in what directory? What is its _actual_ full path as you expect
>>> it to be?
>>
>> Aha. The Blender file that I am using to test this on has two images
>> used as textures. They reside at:
>> /Users/Lion/Desktop/test8/image01.tif
>> /Users/Lion/Desktop/images/image02.tif
>>
>> The Blender file is at /Users/Lion/Desktop/test8/tifftest8.blend
>
> There's a remark on that web page I mentioned that suggests that the
> leading '//' indicates the filename is relative to the Blender model, so
> the context directory for the '//' is likely /Users/Lion/Desktop/test8.
Yes. That makes sense. The reason I was testing with two images, one at
/Users/Lion/Desktop/test8/image01.tif and the other at
/Users/Lion/Desktop/images/image02.tif is that I cannot rely on images
being in the same folder as the Blender file.
So, let's assume the context directory is /Users/Lion/Desktop/test8
and see how we get on below.
>
>>>> (Chris and Peter lead me to believe that Blender has a special kind
>>>> of relative path. The double slashes replace the path to the blend
>>>> file’s directory.) realpath has done something but I know not what.
>
> realpath needs a UNIX path. Your //image01.tif isn't a UNIX path, it is
> a special Blender path. First you need to convert it. By replacing '//'
> with the blend file's directory. Then you can call realpath. If you
> still need to.
Understood. Now. Thanks!
>
> [...snip...]
Did you just [...snip...] yourself?
>>> So you might want to write an unBlenderiser (untested example):
>>>
>>> from os.path import isabs, join as joinpath
>>>
>>> def unblenderise(filename, context_dir=None):
>>> # transmute Blender "relative" path
>>> if filename.startswith('//'):
>>> filename = filename[2:]
>>> if not isabs(filename) and context_dir is not None:
>>> # attach the filename to `context_dir` if supplied
>>> filename = joinpath(context_dir, filename)
>>> return filename
>>>
>>> The idea here is to get back a meaningful UNIX path from a Blender
>>> path. It first strips a leading '//'. Next, _if_ the filename is
>>> relative _and_ you supplied the optional context_dir (eg the
>>> directory used for a file brwoser dialogue box), then it prepends
>>> that context directory.
>>>
>>> This _does not_ call abspath or realpath or anything, it just returns
>>> a filename which can be used with them.
>>>
>>> The idea is that if you know where image01.tif lives, you could
>>> supply that as the context directory.
>>
>> Yes! Until Peter Otten's timely intervention, I was trying to do this
>> and had managed to join the
>> path_to_the_folder_that_contains_the_Blender_file to
>> the_name_of_the_image (stripped of its preceding slashes).
>>
>> Your unblenderise looks much better than my nascent saneblender so
>> thank you. I will explore more!
>
> Looks like you want wd=os.path.dirname(path_of_blend_file).
Thank you!
>
>> Does it depend on knowing where image01.tif lives and manually
>> supplying that?
>
> Sort of.
>
> What you've got is '//image01.tif', which is Blender's special notation
> indicating a filename relative to the blend file's directory. All the
> Python library stuff expects an OS path (OS==UNIX on a Mac). So you want
> to convert that into a UNIX path. For example:
>
> from os.path import dirname
>
> # Get this from somewhere just hardwiring it for the example.
> # Maybe from your 'n' object below?
> blend_file = '/Users/Lion/Desktop/test8/tifftest8.blend'
Is this setting a relative path?
>
> blender_image_file = n.image.filename
>
> unix_image_file = unblenderise(blender_image_file, dirname(blend_file))
>
> Now you have a UNIX path. If blend_file is an absolute path,
> unix_image_path will also be an absolute path. But if blend_file is a
> relative path (eg you opened up "tifftest8.blend") unix_image_path will
> be a relative path.
Does unix_image_path = unix_image_file?
Two possibilities here.
blend_file (and so unix_image_file) is an absolute path OR blend_file
(and so unix_image_file) is a relative path.
I just want to check my understanding. If I supply the path to
blend_file then it is absolute, and if I ask Python to generate the path
to blend_file from within Blender it is relative. Have I got it?
>
> You don't need to use realpath or abspath on that _unless_ you need to
> reference the file from any directory (i.e. _not_ relative to where you
> currently are).
If I decided not to supply the path and so ended up with a relative UNIX
path, I could now use realpath or abspath to find the absolute path.
Have I still got it?
#
I combined your unblenderise and your use of it (see below). Is my
attempt error free?
It works very well. So thank you! I tested it with a Blend file that had
two images, one in the same folder as the Blend file and the other was
in a folder on the Desktop called 'images'.
The initial results were:
Plane uses image01.tif saved at //image01.tif which is at
/Users/Lion/Desktop/test8/image01.tif
Plane uses image02.tif saved at //../images/image02.tif which is at
/Users/Lion/Desktop/test8/../images/image02.tif
BUT as you say, this was easily sorted by using os.path.realpath or
os.path.abspath. Both worked equally well.
Plane uses image01.tif saved at //image01.tif which is at
/Users/Lion/Desktop/test8/image01.tif
Plane uses image02.tif saved at //../images/image02.tif which is at
/Users/Lion/Desktop/images/image02.tif
So, everything now works. Thank you again. I am just a little unclear on
the absolute and relative, hence my questions.
>
> Cheers,
> Cameron Simpson <cs at cskk.id.au>
#some of this can be tidied later
import bpy
import os
from os.path import realpath
from os.path import isabs, join as joinpath
from os.path import dirname
def unblenderise(filename, context_dir=None):
if filename.startswith('//'):
filename = filename[2:]
if not isabs(filename) and context_dir is not None:
# attach the filename to `context_dir` if supplied
filename = joinpath(context_dir, filename)
return filename
blend_file = '/Users/Lion/Desktop/test8/tifftest8.blend'
texture_list = []
for obj in bpy.context.scene.objects:
for s in obj.material_slots:
if s.material and s.material.use_nodes:
for n in s.material.node_tree.nodes:
if n.type == 'TEX_IMAGE':
texture_list += [n.image]
print(obj.name,'uses',n.image.name,'saved
at',n.image.filepath, 'which is at', unblenderise(n.image.filepath,
dirname(blend_file)))
print('Texture list:',texture_list)
More information about the Python-list
mailing list