
James Pye wrote:
The identification of this issue came from an *experiment* attempting to create a *single* "daemonized()" CM that would execute the with-statement's block in a new child process and, of course, not execute it in the parent. At first, I ran into the RuntimeError in the parent process, and then after rewriting the CMs as classes, I realized the futility.
with daemonized(): run_some_subprocess()
Of course it was all possible if I used the component CMs directly:
with parent_trap(): with fork_but_raise_in_parent(): run_some_subprocess()
When updating the PEP with the rejection notice, it occurred to me that it is fairly easy to handle specific use cases like this reasonably cleanly by including a callable in the design that is always used inline in the body of the outermost with statement. For example: @contextmanager def make_daemon() class SkipInParent(Exception): pass def startd(): # Fork process, then raise SkipInParent # in the parent process. The child process # continues running as a daemon. try: yield startd except SkipInParent: pass with make_daemon() as startd: startd() # Daemon code goes here With that approach, since it is startd() that raises the exception rather than __enter__() then __exit__() will always be given the chance to suppress it. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------