Getting original working directory

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Thu Sep 6 20:17:05 EDT 2007


En Thu, 06 Sep 2007 15:47:02 -0300, rave247 rave247 <rave247 at seznam.cz>  
escribi�:

> If I could use os.getcwd() or save the value to some variable before  
> calling os.chdir() I would do it, believe me. However I can't because it  
> is the part of code where I can't do any changes.
>
> Also I do not agree that such thing is not possible because after python  
> script finishes its work, it naturally gets back into the original  
> location from where you started the script (in shell you are in the  
> original location after script finishes). So this information has to be  
> stored somewhere (probably in shell which runs the interpreter) and  
> there *must*  be a way how to get it. Simply after calling os.chdir()  
> the original value doen't disappear, I think it just needs some nice  
> hack if python doesn't provide a way how to get it.

The "current directory" is a per-process attribute managed by the OS.
This is the greatest way to successfully remember the previous directory  
in a step by step recipe:

  - Setup a web service in a trusted server exposing an object implementing  
a queue-like interfase. Ensure your application has the right permissions  
to access the web service (you may have to open a port thru the firewall).  
This part is up to you. The poor man's solution is to use a  
SimpleXMLRPCServer daemon - that might be enough for starting, good  
because it's a full-Python solution but does not scale very well.

  - You will need a unique identifier. See this wikipedia article for some  
info <http://en.wikipedia.org/wiki/Globally_Unique_Identifier>. I'll  
assume you have a CreateGuid() function available (on Windows you can  
install the pywin32 package, get it from sourceforge). (A pid is not  
enough for use in a global service like this).

  - A few lines of code. Save as remember.py anywhere on your Python path  
(maybe lib/site-packages)

<code>
 from xmlrpclib import ServerProxy

class Rememberer(object):

	_guid = _proxy = _queue = None

	def __init__(self, proxy_url):
             self.proxy_url = proxy_url

         def get_guid(self)
             "A GUID to to identify this rememberer"
             if self._guid is None:
                 self._guid = CreateGuid()
             return self._guid
         guid = property(get_guid)

         def get_proxy(self)
             "xmlrpc proxy"
             if self._proxy is None:
                 self._proxy = ServerProxy(self.proxy_url)
             return self._proxy
         proxy = property(get_proxy)

         def get_queue(self)
             """A queue object in the remote server, identified by  
self.guid"""
             if self._queue is None:
                 self._queue = self.proxy.Queue(self.guid)
         queue = property(get_queue)

         def push(self, value):
             self.queue.push(value)

         def peek(self):
             return self.queue.peek()

         def make_remember(self, function, what_to_remember):
             @functools.wraps(function)
             def inner(*args, **kw):
                 self.push(what_to_remember())
                 function(*args, **kw)
             return inner
</code>

  - The rememberer is globally accesible thru your url. You can use it with  
any process you wish, from anywhere in the world. Just make sure your GUID  
creator is good enough - as said on this recent post  
<http://groups.google.com/group/comp.lang.python/msg/76e25141b9963dfb>,  
you should arrange things to wait some time at system startup until the  
system has collected enough bits of entropy to generate a good identifier.

  - We are almost ready! The crucial part is to replace os.chdir with a  
wrapped version:

<code>
import os, remember
rememberer = remember.Rememberer("your.server.url")
replacements = dict(chdir = ('make_remember', (os.chdir, os.getcwd)),
                     prevdir = ('peek', None))
for attr, (fn, args) in replacements.iteritems():
     if args:
         value = getattr(rememberer, fn)(*args)
     else:
         value = getattr(rememberer, fn)
     setattr(os, attr, value)
</code>

Do that as early as possible; I'd put those lines in lib/sitecustomize.py  
(create that file if not already there). See  
http://docs.python.org/lib/module-site.html for info on the Python  
initialization sequence.

  - Now, you have a new function os.prevdir() which returns the directory  
that was current before the last call to os.chdir. The global web service  
holds a full stack of all the previous dirs, and you can extend the  
interfase to retrieve any value if you wish. Just remember the GUID used  
or you won't be able to retrieve anything.

  - Some bits are left as an exercise: there is no provision to remove  
items from the queue, no security enforced, and it's not thread safe (is  
it?).

  - The above code is untested, has no guarantees, standard disclaimers  
apply, use at your own risk, etc... Moreover, since all that mess can be  
replaced by a simple line like:
original_dir = os.getcwd()
or something similar near the top of your script, I would not even  
*attempt* to use it...

-- 
Gabriel Genellina

PS: Sorry! Could not resist...




More information about the Python-list mailing list