How to pass a reference to the current module

J

James Stroud

Steven said:
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.
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)

or

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"
perspective.
[foo]
param1 = float
param2 = 4

[option1]
__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):

[foo]
param1 = float
param2 = 4

[option1]
__module__ = UserDefined1
__function__ = do_something_with
param1 = str
param2 = 30.0

[doit]
param1 = float
param2 = float

[etc.]


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.

James
 
P

Peter Otten

James said:
Yes, those were typos. And to be consistent, the whole listing of the
configuration file should be (note: 'doit'->do_something_with):

[foo]
param1 = float
param2 = 4

[option1]
__module__ = UserDefined1
__function__ = do_something_with
param1 = str
param2 = 30.0

[doit]
param1 = float
param2 = float

[etc.]


With the user's main having the following in it:

from UserDefined1 import some_function
def foo(): [etc.]
def doit(): [etc.]


Why don't you just let your userse write

def foo(param1=float, param2=4):
...

and dump the config file? Alternatively you can devise a decorator

@declare(float, int)
def foo(param1, param2=4):
...

The problem of mapping names to values, be they modules or functions, will
magically vanish.

Peter
 
P

Paul Rubin

James Stroud said:
FunctionUser.do_something_with(globals(), 'doit', 7)

How about instead of "import FunctionUser", require

from FunctionUser import do_something

In FunctionUser.py, write:

frob = (some object that gets necessary stuff from module environment)

def do_something(*user_args, __frob = frob):
# use __frob to access FunctionUser module contents as needed
# ...
(func, args) = getattr(FunctionUser, user_args[0]), user_args[1:]
func(*args)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,609
Members
45,253
Latest member
BlytheFant

Latest Threads

Top