[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

accessing variable of the __main__ module

News123

3/20/2010 12:16:00 PM

Hi,


I wondered about the best way, that a module's function could determine
the existance and value of variables in the __main__ module.


What I came up with is:
########### main.py ##########
import mod
A = 4
if __name__ == "__main__": mod.f()
########### mod.py ##########
def f():
try:
from __main__ import A
except ImportError as e:
A = "does not exist"
print "__main__.A" ,A

Is there anything better / more pythonic?

Thanks in advance and bye


N
6 Answers

Alf P. Steinbach

3/20/2010 12:48:00 PM

0

* News123:
>
> I wondered about the best way, that a module's function could determine
> the existance and value of variables in the __main__ module.
>
>
> What I came up with is:
> ########### main.py ##########
> import mod
> A = 4
> if __name__ == "__main__": mod.f()
> ########### mod.py ##########
> def f():
> try:
> from __main__ import A
> except ImportError as e:
> A = "does not exist"
> print "__main__.A" ,A
>
> Is there anything better / more pythonic?

I don't know if this is what you're after, because it's design level instead of
technical-Python level. But consider the knowledge distribution above. I see it
as like a doctor (main program) telling a nurse (mod.f) to please do something
for which the nurse would require some ImportantFact, which the good doctor
absent-mindedly forgets to tell the nurse. Trying to do as told the nurse
discovers that she needs the ImportantFact, and knowing that it might be
available in one of the doctor's files she breaks into his office, finds the PC
up and running with the doctor logged in, hurray!, and starts looking...

I think the doctor should just give the nurse the ImportantFact right away, not
be so absent-minded and unavailable for query later.

And I think that if the nurse isn't told the ImportantFact and discovers that
she needs it to do what she's told, then the proper thing to do is not to break
into the doctor's office and go browsing in his files to possibly find what she
needs. For example, she might instead raise an exception. Don't know how they do
that in hospitals, though.


Cheers & hth.,

- Alf

Steven D'Aprano

3/20/2010 1:06:00 PM

0

On Sat, 20 Mar 2010 13:16:08 +0100, News123 wrote:

> Hi,
>
>
> I wondered about the best way, that a module's function could determine
> the existance and value of variables in the __main__ module.
>
>
> What I came up with is:
> ########### main.py ##########
> import mod
> A = 4
> if __name__ == "__main__": mod.f()
> ########### mod.py ##########
> def f():
> try:
> from __main__ import A
> except ImportError as e:
> A = "does not exist"
> print "__main__.A" ,A
>
> Is there anything better / more pythonic?


First problem:

You try to import from "__main__", but the other module is called "main".
__main__ is a special name, which Python understands as meaning "this
module that you are in now". For example:

$ cat test_main.py
x = "something special"
import __main__ # magic alias for this module
print __main__.x

$ python test_main.py
something special

So inside "mod.py", the line "from __main__ import A" tries to import A
from mod.py, not from main.py. You need to say "from main import A"
instead.

But if you do this, it creates a second problem: you have a circular
import, which is generally considered a Bad Thing. The problem is that:

(1) module main tries to import module mod
(2) module mod tries to import module main
(3) but main is still waiting for mod to be imported

Now, in your case you escape that trap, because the import is inside a
function, so it doesn't occur until you call the function. But it is
still considered poor practice: it is best to avoid circular imports
unless you really, really need them.


The question is, why does module mod.py care what is happening in
main.py? It is better for mod.py to be self-contained, and not care about
main.py at all. If it needs A, let the caller pass A to it:

########### main.py ##########
import mod
A = 4
if __name__ == "__main__":
mod.f(__name__, A)

########### mod.py ##########
def f(caller, A):
print "%s.A: %s" % (caller, A)



--
Steven

News123

3/20/2010 1:32:00 PM

0

Hi Steven,








Steven D'Aprano wrote:
> On Sat, 20 Mar 2010 13:16:08 +0100, News123 wrote:
>
>> Hi,
>>
>>
>> I wondered about the best way, that a module's function could determine
>> the existance and value of variables in the __main__ module.
>>
>>
>> What I came up with is:
>> ########### main.py ##########
>> import mod
>> A = 4
>> if __name__ == "__main__": mod.f()
>> ########### mod.py ##########
>> def f():
>> try:
>> from __main__ import A
>> except ImportError as e:
>> A = "does not exist"
>> print "__main__.A" ,A
>>
>> Is there anything better / more pythonic?
>
>
> First problem:
>
> You try to import from "__main__", but the other module is called "main".
> __main__ is a special name, which Python understands as meaning "this
> module that you are in now". For example:
My choice of names was perhaps not very smart.
I could have called main.py also mytoplevel.py


>
> $ cat test_main.py
> x = "something special"
> import __main__ # magic alias for this module
> print __main__.x
>
> $ python test_main.py
> something special
>
> So inside "mod.py", the line "from __main__ import A" tries to import A
> from mod.py, not from main.py. You need to say "from main import A"
> instead.
>
I think you're wrong, my above code seems to work.
__main__ refers not to the current module, but to the urrent
'top-level-module'
so
from __main__ import A tries to import from the top level module which
is in my case main.py.


> But if you do this, it creates a second problem: you have a circular
> import, which is generally considered a Bad Thing. The problem is that:
>
> (1) module main tries to import module mod
> (2) module mod tries to import module main
> (3) but main is still waiting for mod to be imported
>
> Now, in your case you escape that trap, because the import is inside a
> function, so it doesn't occur until you call the function. But it is
> still considered poor practice: it is best to avoid circular imports
> unless you really, really need them.
>
>
> The question is, why does module mod.py care what is happening in
> main.py? It is better for mod.py to be self-contained, and not care about
> main.py at all. If it needs A, let the caller pass A to it:


The reason is pure lazyness.
I would like to 'try' something quickly.

I have a module used by many different python programs.

In case the __main__ module contains a certain object I'd like to
extract information from this object if not not.

This is for debug, not for 'production'.

I'd prefer to change only one file and not many.


>
> ########### main.py ##########
> import mod
> A = 4
> if __name__ == "__main__":
> mod.f(__name__, A)
>
> ########### mod.py ##########
> def f(caller, A):
> print "%s.A: %s" % (caller, A)
>
>
>

N

Steven D'Aprano

3/20/2010 2:05:00 PM

0

On Sat, 20 Mar 2010 14:32:03 +0100, News123 wrote:

>> You try to import from "__main__", but the other module is called
>> "main". __main__ is a special name, which Python understands as meaning
>> "this module that you are in now". For example:
>
> My choice of names was perhaps not very smart. I could have called
> main.py also mytoplevel.py
[...]
> I think you're wrong, my above code seems to work. __main__ refers not
> to the current module, but to the urrent 'top-level-module'
> so
> from __main__ import A tries to import from the top level module which
> is in my case main.py.

Hmmm... it looks like you are correct and I made a mistake.

This isn't something that the documentation is clear about, but here are
a set of test files:


$ cat A.py
import __main__
import B
print __main__, B, B.__main__

$ cat B.py
import __main__

$ python A.py
<module '__main__' from 'A.py'> <module 'B' from '/home/steve/python/
B.pyc'> <module '__main__' from 'A.py'>


Here is the documentation:

http://docs.python.org/library/__m...

which is pretty sparse.



--
Steven

Dave Angel

3/20/2010 2:50:00 PM

0

News123 wrote:
>
> Steven D'Aprano wrote:
>
>> <snip>
>> Now, in your case you escape that trap, because the import is inside a
>> function, so it doesn't occur until you call the function. But it is
>> still considered poor practice: it is best to avoid circular imports
>> unless you really, really need them.
>>
>>
>> The question is, why does module mod.py care what is happening in
>> main.py? It is better for mod.py to be self-contained, and not care about
>> main.py at all. If it needs A, let the caller pass A to it:
>>
>
>
> The reason is pure lazyness.
> I would like to 'try' something quickly.
>
> I have a module used by many different python programs.
>
> In case the __main__ module contains a certain object I'd like to
> extract information from this object if not not.
>
> This is for debug, not for 'production'.
>
> I'd prefer to change only one file and not many.
>
>
>
First, the practical response: yes, it'll work, and if this is really
for debug, it's fine. However, realize that many times "debug things"
make it into the wild.

Any time recursion of imports occurs, it's a sign of trouble. And doing
it right isn't usually much harder than studying the hazards of the
recursion.

In the particular case you're doing, I think there are at least three
better solutions:

1) Pass A as an argument to a function call, for example f(A).
2) Put A into a separate module that both main.py and mod.py import
3) Explicitly add A to mod.py's global space. mod.A = A written in
main.py, before calling the function mod.x().

HTH
DaveA

Jean-Michel Pichavant

3/22/2010 11:01:00 AM

0

News123 wrote:
> Hi,
>
>
> I wondered about the best way, that a module's function could determine
> the existance and value of variables in the __main__ module.
>
>
> What I came up with is:
> ########### main.py ##########
> import mod
> A = 4
> if __name__ == "__main__": mod.f()
> ########### mod.py ##########
> def f():
> try:
> from __main__ import A
> except ImportError as e:
> A = "does not exist"
> print "__main__.A" ,A
>
> Is there anything better / more pythonic?
>
> Thanks in advance and bye
>
>
> N
>
The 'was I imported from that module' is usually some sign of bad
design. I can't detail more wihtout further detail of what you're trying
to achieve. Bud since what you have is working, I would'nt bother more
than that cause no matter what you try, it will be ugly :o).

JM