absolute path to a file

Paul St George email at paulstgeorge.com
Tue Aug 20 15:06:54 EDT 2019


On 20/08/2019 11:43, Cameron Simpson wrote:
> Please remember to CC the list.
Instead of 'Post a followup to this newsgroup' or 'To: 
python-list at python.org'?

> 
> On 19Aug2019 22:06, Paul St George <email at paulstgeorge.com> wrote:
>> On 19/08/2019 14:16, Cameron Simpson wrote:
> [...]
>>> 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.
> [...]
>>> 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?
> 
> Yes. It keeps the surrounding context manageable. In this way you know 
> to which text I am referring, without having to wade through paragraphs 
> to guess what may be relevant.
> 
>>>    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?
> 
> Yeah, sorry,  my mistake.
> 
>> 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?
> 
> Not quite. What seems to be the situation is:
> 
> You've got some object from Blender called "n.image", which has a 
> ".file" attribute which is a Blender reference to the image file of the 
> form "//image01.tif".
> 
> I presume that Blender has enough state inside "n" or "n.image" to 
> locate this in the real filesystem; maybe it has some link to the 
> Blender model of your blend file, and thus knows the path to the blend 
> file and since //image01.tif is a reference relative to the blend file, 
> it can construct the UNIX path to the file.
> 
> You want to know the UNIX pathname to the image file (maybe you want to 
> pass it to some unrelated application to view the file or something).

Exactly. I am using Python to log a series of experiments. If I have a 
record of the settings and the assets used, I can better learn from what 
works and so repeat the successes and avoid the failures.
> 
> So you need to do what Blender would do if it needs a UNIX path (eg to 
> open the file).
> 
> The formula for that is dirname(path_to_blendfile) with n.image.file[2:] 
> appended to it. So that's what we do with unblenderise(): if the 
> filename is a "Blender relative name", rip off the "//" and prepend the 
> blend file directory path. That gets you a UNIX path which you can hand 
> to any function expecting a normal operating system pathname.
> 
> Whether that is an absolute path or a relative path is entirely "does 
> the resulting path start with a '/'"?

We used
blend_file = '/Users/Lion/Desktop/test8/tifftest8.blend'
So, if I read you correctly, this is an absolute path.

When we used unblenderise on it, out popped a path that was partly but 
not wholly relative. The latter half of the path is relative to the 
absolute first half (/Users/Lion/Desktop/test8/).

/Users/Lion/Desktop/test8/../images/image02.tif

It starts with a slash but cannot be pasted into "Go to...". But maybe 
that is an absolute path in UNIX?

> 
> An absolute path starts with a slash and is relative to the root of the 
> filesystem. You can use such a path regardless of what your current 
> working directory is, because it doesn't use the working directory.

> 
> A relative path doesn't start with a slash and is relative to the 
> current working directory. It only works if you're in the right working 
> directory.
> 
> _Because_ a relative path depends on the _your_ working directory, 
> usually we pass around absolute paths if we need to tell something else 
> about a file, because that will work regardless if what _their_ working 
> directory may be.
> 
> So, you may well want to turn a relative path into an absolute path...
> 
>> 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?
> 
> This is correct.
> 
> Abspath may even call realpath to do its work, unsure.
> 
>> 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.
> 
> Yep. Abspath does some things in a purely lexical way: it resolves '.' 
> and '..' components in the path even if they don't exist. For example it 
> resolves 'a/b/c/d/../../../../foo' for me even though here 'a/b/c/d' 
> doesn't exist: it see the '.. and strips off the preceeding component, 
> repeatedly. So it starts with 'foo' after that pahse  and prepends the 
> working directory path.
> 
> The system realpath is not documented to work if some of the path is 
> fictitious, but the Python realpath seems to work even then, maybe it 
> falls back to abspath or something.
> 
> Abspath takes a relative path and returns you an absolute path with the 
> '.' and '..' components stripped out.
> 
> Realpath follows symlinks and stuff and returns you the direct absolute 
> path _after_ all that - one that doesn't traverse symlinks.
> 
> For your purposes the results are equally functional.
> 
>> 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.
> 
> Hope the above xaplinations help.
Yes, very much. Thank you.
> 
> Cheers,
> Cameron Simpson <cs at cskk.id.au>





More information about the Python-list mailing list