On Sat, 13 Feb 2010 10:51:38 am Garry Willgoose wrote: > I want to be able to import multiple instances of a module and call > each by a unique name and it doesn't appear at first glance that > either import or __import__ have what I need.
No, such a thing is not officially supported by Python. Python treats modules as singletons -- there is only one instance of any module at any time. It is possible to force Python to break that promise, but that is fighting the language, and there's no guarantee that it won't cause other breakages further along. So if you choose to create multiple instances of a module, you're doing something the language doesn't want you to do, and if you end up shooting yourself in the foot you'll have no one to blame but yourself. Having said that, the following trick should do what you want. Start with a simple module holding state: # mymodule.py state = [] Here's Python's normal behaviour: >>> import mymodule >>> mymodule.state [] >>> mymodule.state.append(123) >>> mymodule.state [123] >>> import mymodule as something_else >>> something_else.state [123] And here's the trick: >>> import sys >>> del sys.modules['mymodule'] >>> import mymodule as another_name >>> another_name.state [] >>> mymodule.state # Check the original. [123] This *should* work across all versions and implementations of Python, but remember that it's a hack. You're fighting the language rather than working with it. Another problem is that there's no guarantee that the module holds all its state inside itself: it might in turn import a second module, and store state in there. Many packages, in particular, may do this. The best solution is to avoid global state if you possibly can. You also say: > The key problem is that > the module might locally store some partial results ready for the > next time its called to save CPU time (typically the results for one > timestep ready for the next timestep). I'm going to take a wild guess as to what you're doing, and make a suggestion for how you can do something better. I guess you have functions something like this: STATE = None def func(): global STATE if STATE is None: # No global state recorded, so we start from scratch. step = 1 partial = 0 else: step, partial = STATE step += 1 partial = do_some_calculations(step, partial) STATE = (step, partial) return partial But as you point out, that means all calls to func() use the same global state. Here are two alternatives. Here's a rather messy one, but it tickles my fancy: use a token to identify the caller, so each caller gets their own state and not somebody else's. LAST_TOKEN = 0 def get_token(): global LAST_TOKEN LAST_TOKEN += 1 return LAST_TOKEN STATE = {} def func(token): global STATE if not STATE[token]: # No global state recorded, so we start from scratch. step = 1 partial = 0 else: step, partial = STATE[token] step += 1 partial = do_some_calculations(step, partial) # Defined elsewhere. STATE[token] = (step, partial) return partial Then, before each independent use of func, the caller simply calls get_token() and passes that to the function. I'm sure you can see problems with this: - the caller has to store their tokens and make sure they pass the right one; - the function needs to deal with invalid tokens; - the global STATE ends up storing the result of intermediate calculations long after they are no longer needed; - the separation is a "gentleman's agreement" -- there is nothing stopping one caller from guessing another valid token. Although I'm remarkably fond of this solution in theory, in practice I would never use it. A better solution is to write func in a more object-oriented fashion: class FuncCalculator(object): """Class that calculates func""" def __init__(self): # Start with initial state. self.STATE = (1, 0.0) def __call__(self): step, partial = self.STATE step += 1 partial = self.do_some_calculations(step, partial) self.STATE = (step, partial) return partial def do_some_calculations(self, step, partial): return partial + 1.0/step # or whatever Instances of the class are callable as if they were functions. In C++ terminology, this is called a "functor". In Python, we normally just call it a callable. So we can create as many independent "functions" as needed, each with their own state: >>> f = FuncCalculator() >>> g = FuncCalculator() >>> h = FuncCalculator() >>> f() 0.5 >>> f() 0.83333333333333326 >>> f() 1.0833333333333333 >>> g() 0.5 >>> g() 0.83333333333333326 >>> h() 0.5 >>> f() 1.2833333333333332 Hope this helps! -- Steven D'Aprano _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor