# Python 3 minor irritation

Alf P. Steinbach alfps at start.no
Thu Feb 4 06:20:47 CET 2010

* Benjamin Kaplan:
> On Wed, Feb 3, 2010 at 11:18 PM, Alf P. Steinbach <alfps at start.no> wrote:
>> * Benjamin Kaplan:
>>> On Wed, Feb 3, 2010 at 9:56 PM, Alf P. Steinbach <alfps at start.no> wrote:
>>>> * David Monaghan:
>>>>> I have a small program which reads files from the directory in which it
>>>>> resides. It's written in Python 3 and when run through IDLE or PythonWin
>>>>> works fine. If I double-click the file, it works fine in Python 2.6, but
>>>>> in
>>>>> 3 it fails because it looks for the files to load in the Python31
>>>>> folder,
>>>>> not the one the script is in.
>>>>>
>>>>> It's not a big deal, but browsing around I haven't found why the
>>>>> behaviour
>>>>> has been changed or any comment about it (That might be my poor search
>>>>> technique, I suppose).
>>>>>
>>>>> The program fails at:
>>>>>
>>>>>   try:
>>>>>       tutdoc = minidom.parse(".//Myfile.xml")
>>>>>   except IOError:
>>>>>       <snip>
>>>> The "//" is wrong, but should not cause the behavior that you describe.
>>>>
>>>> Try to post a complete smallest possible program that exhibits the
>>>> problem.
>>>>
>>>> Possibly, in creating that example you'll also find what's cause the
>>>> problem. :-)
>>>>
>>>>
>>>> Cheers & hth.,
>>>>
>>>> - Alf
>>> That is the smallest example the exhibits the problem.
>> No, it doesn't seem to exhibit the problem at all. :-)
>>
>>
>>> It's not an
>>> issue with the Python code, it's an issue with how Windows is running
>>> it. I don't know enough about the way Windows Explorer runs files, but
>>> it seems to be doing the equivalent of
>>> cd C:\Python31
>>> python31.exe C:\full\path\to\script\foo.py
>>>
>>> cd C:\full\path\path\to\script
>>> C:\Python31\python.exe foo.py
>>> which is David expected. This throws off the relative filepath.
>> No, this is not what happens.
>>
>> What happens is that when you double-click the script, then __file__ is set
>> to the absolute path instead of just the filename, at least on my machine
>> (XP); whether the full path or just the filename is passed on the OS level
>> depends, however, on the Windows version.
>>
>> The current directory is always (initially) correct, as the script's
>> directory.
>>
>
> Read my first paragraph again- it has absolutely nothing to do with
> Python. It has to do with how the Windows is running Python 3 on the
> OP's computer.

I'm not sure what you're arguing here.

But anyway, first, I haven't stated that "it" is (only) an issue with Python: on
the contrary, I explained how the program is run by Windows Explorer, where in
Windows XP the full path is passed by Windows Explorer, and how that results in
(can result in) a full path in __file__ when a script is run by double-clicking.

So the explanation of an incorrect result involves not only Windows Explorer,
the Windows version, and Python, but also the OP's code is involved.

Hence the request for a minimal, complete example  --  which is nearly always a
good idea.

> The OP's description said that it was looking for the
> file .\\myfile.xml in C:\Python31 which means it translated '.', the
> current working directory, to be C:\Python31 and not the directory the
> script is in.

I fail to reproduce that behavior.

By the way, are you the OP (just with another name)?

If not, have you reproduced the described behavior? Then kindly post the code.

>>> The easiest way to solve this permanently, by the way, is to not use
>>> relative paths. All it takes is one script to call os.chdir and the
>>> script breaks. You can use __file__ and the os.path module to figure
>>> out exactly where you are in an OS-agnostic way.
>>>
>>> import os.path
>>> #get the absolute path to the current script
>>> abs_path = os.path.abspath(__file__)
>> According to the docs: "On most platforms, this is equivalent to
>> normpath(join(os.getcwd(), path))."
>>
>
> os.path.abspath will always work in this case (unless something
> changes the current working directory before that statement runs)

Which change is what you surmised as a cause of the original problem.

Hello.

> because __file__ is given either as an absolute path or as relative to
> the current working directory.

No, that's incorrect.

<code py="3.1">
import os

print( "Current directory: [" + os.getcwd() + "]" )
print( "__file__ = " + __file__ )
os.chdir( "blah" )
print( "Current directory: [" + os.getcwd() + "]" )
print( "__file__ = " + __file__ )
</code>

<example>
C:\Documents and Settings\Alf\test> python curdir.py
Current directory: [C:\Documents and Settings\Alf\test]
__file__ = curdir.py
Current directory: [C:\Documents and Settings\Alf\test\blah]
__file__ = curdir.py                    <-- *Not* relative to cwd.

C:\Documents and Settings\Alf\test> _
</example>

[snip]
> Except that if the cwd is not the directory the script is running in,
> __file__ should still point to it either through an absolute path
> (highly likely since it's run through Windows Explorer) or some
> (however convoluted) relative path.

Don't know about "should", but if you're talking reality, no, that's incorrect;
see above.

[snip]

Cheers & hth.,

- Alf