How to pass a reference to the current module
jstroud at mbi.ucla.edu
Sat Aug 4 10:52:28 CEST 2007
Steven D'Aprano wrote:
> I suggest you're falling for the anti-pattern of "Big Design Up Front",
> and are overly complicating your system "just in case it's useful". Why
> not just _insist_ that main.py and UserDefined1.py must be different
> modules? You're the application developer, you're allowed to do that.
The idea of the module I'm writing is to allow the user to define
functions where they want and to create single-file python scripts that
can make use of my API. The point of the module is to be beginner
friendly, but maybe that is asking too much as user friendliness might
be a potentially useful but provably unnecessary attribute.
>> 2. foo is defined in `main`
> Maybe you should just prohibit that? Do you really want to allow users to
> call arbitrary code in your main application at arbitrary times and places?
It would be the user's main and they would be importing my module. I
would like my module to be aware of the contents of the user's module. I
thought such a thing would be possible because it seems like something
similar is happening in distutils py2app.
> But in any case, it shouldn't matter. main is the program running -- it
> has to be, because you can't import it from another program -- so
> globals()['foo'] will work.
>> Possibility two (even when it is a properly named module) sets the stage
>> for a circular import, but I believe in python this is not entirely
>> worrisome. However, the combination above makes it difficult to pass a
>> reference to the `main` namespace without some sort of introspection.
> That's what globals() is for.
On second thought this might not be horribly bad:
FunctionUser.do_something_with(globals(), 'doit', 7)
FunctionUser.do_something_with(UserDefined1.globals(), 'foo', 7)
From a beginner-user's perspective (i.e. potential users of my module),
it seems a little awkward, but might be more natural on the whole than
the alternatives. However, if I had my druthers, I would rather have
some way to pass a reference to the current module in the former case
and have do_something_with() call globals(). I really like the idea of
having the module or its namespace as an optional argument and
implicitly using the calling global namespace if its left out. But
perhaps this is bad design from an "explicit is better than implicit"
>> param1 = float
>> param2 = 4
>> __module__ = 'UserDefined1'
>> __function__ = 'doit'
> I'm not sure why you need the quotation marks around the module and
> function names. What else could UserDefined1 be, other than a string?
Yes, those were typos. And to be consistent, the whole listing of the
configuration file should be (note: 'doit'->do_something_with):
param1 = float
param2 = 4
__module__ = UserDefined1
__function__ = do_something_with
param1 = str
param2 = 30.0
param1 = float
param2 = float
With the user's main having the following in it:
from UserDefined1 import some_function
def foo(): [etc.]
def doit(): [etc.]
I'm afraid my previous listing of the config file could cause confusion.
More information about the Python-list