[Python-ideas] chdir context manager

Daniel Shahaf d.s at daniel.shahaf.name
Sat Jan 19 16:06:31 CET 2013


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.

> 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__()?

> Looking at your pattern, if foo() does not change cwd, the save and  
> restore is pointless, even if harmless.

Do you have a better suggestion?  Determining whether the fchdir() call
can be avoided, if possible, presumably requires a system call, so
I figure you might as well call fchdir() without trying to make that
determination.

> If foo does change cwd, it  should also restore it, whether explicitly
> or with a context manager  temp_cwd.
>
> Looking at your actual example, shutil.make_archive, the change and  
> restore are conditional and asymmetrical.
>

shutil.make_archive is just the first place in stdlib which uses the
pattern, or something close to it.  It's not exactly a canonical
example.  There are some canonical examples of the "pattern" in
test_os.py.

> -- 
> Terry Jan Reedy

Cheers

Daniel



More information about the Python-ideas mailing list