0

I am searching for a way to run a module while replacing imports. This would be the missing magic to implement run_patched in the following pseudocode.

from argparse import ArgumentParser

class ArgumentCounter(ArgumentParser):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        arg_counter = 0
    def add_argument(self, *args, **kwargs):
        super().add_argument(*args, **kwargs)
        arg_counter += 1
    def parse_args(self, *args, **kwargs):
        super().parse_args(*args, **kwargs)
        print(arg_counter)

run_patched('test.test_argparse', ArgumentParser = ArgumentCounter)

I know that single methods could be replaced by assignment, for example stating ArgumentParser.parse_args = print, so I was tempted to mess with globals like sys.modules and then execute the module by runpy.run_module.

Unfortunately, the whole strategy should be able to work in a multithreaded scenario. So the change should only affect the module executed while other parts of the program can continue to use the unpatched module(s) as if they were never touched.

XZS
  • 2,374
  • 2
  • 19
  • 38
  • Modules are inherently global objects. Making this work multithreaded is going to be difficult (assuming it's even possible) and you will be fighting the interpreter every step of the way. Why can't you run a separate interpreter instance? – Kevin Dec 09 '14 at 15:41
  • I would also consider starting up a dedicated interpreter instance. But the object I want to pass in is much more complex than the example. As far as I know, I would have to serialize it to pass it into another runtime, which wold be considerably difficult. – XZS Dec 09 '14 at 16:52
  • The only thing I can think of is to replace the `argparse` module in `sys.modules` with some kind of magic proxy object that overrides `__getattr__`, providing different behavior on different threads. But that's [purest evil](http://c2.com/cgi/wiki?ThreeStarProgrammer). – Kevin Dec 09 '14 at 17:02

0 Answers0