2

I have a python module_A which is doing something like this:

myvar = "Hello"

def message():
    print myvar

From another module, I want to import the function message:

from module_A import message

But this is defining myvar, which I do not want (for reasons not really relevant here). I guess what I need is to make a distinction between importing things from a module, and using any of the imported symbols. I actually want myvar to be initialized only when I use message.

I there any kind of python hook that I could use to initialize stuff whenever a function or class is accessed? I would like something similar to the following:

module_setup_done = False
def setup():
    global module_setup_done, myvar
    if not module_setup_done:
        myvar = "Hello"
        module_setup_done = True

def message():
    setup()
    print myvar

But, to reduce clutter, I would like this to be called automatically, something like this:

def _init_module():
    global myvar
    myvar = "Hello"

def message():
    print myvar

Where _init_module() would be called only once, and only the first time that something in the module is accessed, not when something is imported.

Is there support for this kind of pattern in python?

blueFast
  • 41,341
  • 63
  • 198
  • 344

1 Answers1

4

No, there is no built-in support for this. If you want to initialize things separately from importing the module, write a function that does that initialization, then call the function when you want to initialize those things. If you want to "automatically" initialize things when other things are called, you have to handle that yourself with code along the lines of what you already posted.

If you find yourself doing that, though, you're probably doing something unpythonic. You don't give details about why you're doing it here, but in general this sort of implicit initialization is not a good practice in Python. Things are initialized when you explicitly tell them to be, for instance by importing a module or calling some sort of initialization function. Why do you feel the need to have this separate, implicit initialization step?

BrenBarn
  • 242,874
  • 37
  • 412
  • 384
  • I will try to summarize: my global variable is actually a caching-thread in a celery module, where some celery tasks are defined. I have a client for this celery module, which must import the celery tasks, but does not really execute the tasks (it will just broker them via celery). The point is that when I am doing unit testing of my client, because it is importing the symbols from the celery module, the caching-thread is initialized and started, even though this is not needed at all in the client. Because of this supurious thread, the unittest does not end. – blueFast Oct 11 '12 at 05:45
  • In that case, a simpler solution might be to use an if/else around myvar based on whether you're running a test or not. Presumably there is some way to distinguish between normal execution and unit test execution, and you could then do: myvar = caching_thread if not in_test_mode else None – Jeremy Lewis Oct 11 '12 at 05:51
  • Yeah, I would do something like what Jeremy Lewis suggests. What you really want to do is somehow mark the test usage and do things differently in that case. One way would just be to have an initializing function like I describe, and not call it during the test. Then you'd have to call it manually for non-test usage, but that's not so bad. – BrenBarn Oct 11 '12 at 06:05
  • You could use __ to designate variables which are not to be imported in the calling module - that way they will be 'name mangled' so they are guaranteed not to interfere. http://stackoverflow.com/questions/1301346/what-is-the-meaning-of-a-single-and-a-double-underscore-before-an-object-name has more information on this. – babelmonk May 17 '17 at 17:10