
On 14Sep2021 21:43, M.-A. Lemburg <mal@egenix.com> wrote:
- The context manager is not thread safe. There's no thread safe model for the current work dir. OTOH, scripts usually don't use threads, so not a big deal.
This is the source of my concerns. Though of course it applies to any process global state. It would need this stated up front in big letters (as of course does chdir itself). My real concern is that this can leak into other functions whose use then makes whatever uses them to become inherently and unrepairably not thread safe. I know I'm atypical, but I have quite a lot of multithreaded stuff, including command line code. So while it'd be ok to avoid this context manager for my own code, I fear library modules, either stdlib or pypi, quietly using this in their code, making them unuseable in the general case. Unrepairably unuseable, for the user. I think what would be more useful is a context manager which worked on a threading.local which pushed/popped a reference directory path, and had an open() method which used that (and friends for other pathname based functions). In my own code I'd write this like (sketch, untested): from cs.threads import State as ThreadState class RefDir(ThreadState) def __init__(self, refpath=None): if refpath is None: refpath = os.getcwd() self.refpath = abspath(refpath) def open(self, path, *a, **kw): if not isabs(path): path = os.path.join(self.refpath, path) return open(path, *a, **kw) # calls the builtin open() ... listdir, mkdir, etc etc ... # on reflection, __enter__ and __exit__ would make the below even # more convenient @contextmanager def dirpath(newrefpath): ''' Push `newrefpath` for the duration of the context manager. ''' with self(refpath=newrefpath): yield self.refpath and then use it like this: R = RefDir() .... with R.dirpath('/some/new/place') as newpath: ... with R.open("something.txt") as f: ... work on /some/new/place/something.txt ... In the above, cs.threads.State is a threading.lcoal subclass which is also a context manager whose operation pushes arbitrary attribute values. Great for thread safe execution scoped state. Like this example. All that said, I wrote pretty much exactly what you describe just the other week for umask(). Cheers, Cameron Simpson <cs@cskk.id.au>