[Python-ideas] chdir context manager

Daniel Shahaf d.s at daniel.shahaf.name
Sun Jan 20 05:43:08 CET 2013


MRAB wrote on Sat, Jan 19, 2013 at 18:32:21 +0000:
> On 2013-01-19 18:07, Terry Reedy wrote:
>> On 1/19/2013 10:06 AM, Daniel Shahaf wrote:
>>> Terry Reedy wrote on Sat, Jan 19, 2013 at 08:37:17 -0500:
>>>> On 1/19/2013 5:10 AM, Daniel Shahaf wrote:
>>>>> The following is a common pattern (used by, for example,
>>>>> shutil.make_archive):
>>>>>
>>>>>       save_cwd = os.getcwd()
>>>>>       try:
>>>>>           foo()
>>>>>       finally:
>>>>>           os.chdir(save_cwd)
>>>>>
>>>>> I suggest this deserves a context manager:
>>>>>
>>>>>       with saved_cwd():
>>>>>           foo()
>>>>
>>>> So to me, your proposal is only 1/2 or 2/3 of a context manager. (And
>>>> 'returns an open file descriptor for the saved directory' seems backward
>>>> or wrong for a context manager.) It does not actually make a new
>>>
>>> What should __enter__ return, then?
>>>
>>> It could return None, the to-be-restored directory's file descriptor, or
>>> the newly-changed-to directory (once a "directory to chdir to" optional
>>> argument is added).  The latter could be either a pathname (string) or
>>> a file descriptor (since it's just passed through to os.chdir).
>>>
>>> It seems to me returning the old dir's fd would be the most useful of
>>> the three option, since the other two are things callers already have
>>> --- None, which is global, and the argument to the context manager.
>>
>> make_archive would prefer the old dir pathname, as it wants that for the
>> logging call. But I do not think that that should drive design.
>>
>>>> context. A proper temp_cwd context manager should have one parameter,
>>>> the new working directory, with chdir(new_cwd) in the enter method. To
>>>> allow for conditional switching, the two chdir system calls could be
>>>> conditional on new_cwd (either None or '' would mean no chdir calls).
>>>>
>>>
>>> I think making the new_cwd argument optional would be useful if the
>>> context manager body does multiple chdir() calls:
>>>
>>>      with saved_cwd():
>>>          os.chdir('/foo')
>>>          do_something()
>>>          os.chdir('/bar')
>>>          do_something()
>>>
>>> I'm not sure if that's exactly what you suggest --- you seem to be
>>> suggesting that saved_cwd(None) will avoid calling fchdir() from
>>> __exit__()?
>>
>> I was, but that is a non-essential optimization. My idea is basically
>> similar to Bueno's except for parameter absent versus None (and the two
>> cases could be handled differently).
>>
>> I think this proposal suffers a bit from being both too specific and too
>> general. Eli explained the 'too specific' part: there are many things
>> that might be changed and changed back. The 'too general' part is that
>> specific applications need different specific details. There are various
>> possibilities of what to do in and return from __enter__.
>>

OK.

>> However, given the strong -1 from at least three core developers and
>> one other person, the detail seem moot.
>>

*nod*, I see.

> FWIW, -1 from me too because, as has been said already, you shouldn't  
> really be using os.chdir; use absolute paths instead.

I don't use chdir in library code or multithreaded code, but I do use it
in __main__ of short scripts, where there's no "caller" or "other
thread" to consider.

Consider sys.argv.  The language and stdlib don't prevent library code
from accessing (or modifying) sys.argv, but well-behaved libraries
neither read sys.argv nor modify it.  The same is true of the cwd.



More information about the Python-ideas mailing list