Testing if a global is defined in a module

T

Tim Johnson

Using Python 2.6 on ubuntu 10.04.
inspect module :
I want to 'inspect' a module and get a list of all
functions, classes and global variables in that module.

## A module has been imported, and we call `getmembers'
members = inspect.getmembers(mod)

## While iterating thru `members', we test to see
## if an object is defined in the module.
for m in members:
obj = m[1]
res = inspect.getmodule(obj)
## It appears that getmodule returns None for
## all but functions and classes.

Example, for a module name `mvcInstall', when a class
name `Install' that is defined in the module
is passed as an argument to inspect.getmodule, the
values returned is something like
"<module 'mvcInstall' from
'/home/tim/prj/cgi/libraries/python/mvcInstall.py'>"
Likewise for functions defined in the module.

** But ** when global variables such as strings, booleans,
integers are passed as an argument to getmodule, the
value returned is `None'.

What else can I do here?
thanks
 
R

rantingrick

Using Python 2.6 on ubuntu 10.04.
inspect module :
I want to 'inspect' a module and get a list of all
functions, classes and global variables in that module.

## A module has been imported, and we call `getmembers'
members = inspect.getmembers(mod)

## While iterating thru `members', we test to see
## if an object is defined in the module.
for m in members:
  obj = m[1]
  res = inspect.getmodule(obj)
## It appears that getmodule returns None for
## all but functions and classes.

Example, for a module name `mvcInstall', when a class
name `Install' that is defined in the module
is passed as an argument to inspect.getmodule, the
values returned is something like
"<module 'mvcInstall' from
'/home/tim/prj/cgi/libraries/python/mvcInstall.py'>"
Likewise for functions defined in the module.

** But ** when global variables such as strings, booleans,
integers are passed as an argument to getmodule, the
value returned is `None'.

What else can I do here?
thanks

Well if you follow the python style guide (and most accepted styles
for global notation) then it's a trial exercise. You don't even have
to import anything!!! :)
['GLOBAL_FLOAT', 'GLOBAL_STR', 'GLoBaL_Bs', '__builtins__', '__doc__',
'__name__', '__package__', 'item']if item.isupper():
print 'Found Global!', item


Found Global! GLOBAL_FLOAT
Found Global! GLOBAL_STR

;-)
 
T

Tim Johnson

* rantingrick said:
Well if you follow the python style guide (and most accepted styles
for global notation) then it's a trial exercise. You don't even have
to import anything!!! :)
['GLOBAL_FLOAT', 'GLOBAL_STR', 'GLoBaL_Bs', '__builtins__', '__doc__',
'__name__', '__package__', 'item'] if item.isupper():
print 'Found Global!', item
Thanks for the reply: *but*

dir(<targetmodule>) will also show globals from other modules imported
by the target module. So I would need a way to distinguish between
those imported and those defined in <targetmodule>
print(dir(targetmodule)) =>
['Install', 'TestAddresses', '__builtins__', '__doc__',
'__file__', '__name__', '__package__', 'chmod', 'consoleMessage',
'cp', 'debug', 'erh', 'exists', 'halt', 'is_list', 'load',
'makePath', 'mkdir', 'process', 'sys', 'traceback', 'usingCgi']
where 'TestAddresses' is a member of an imported module and
'usingCgi' is the only data variable defined in <targetmodule>

regards
 
R

rantingrick

  Thanks for the reply: *but*
  dir(<targetmodule>) will also show globals from other modules imported
  by the target module. So I would need a way to distinguish between
  those imported and those defined in <targetmodule>

Okay, then do some processing on the source. You can use regexps or
the module mentioned earlier by Chris.
 
T

Tim Johnson

* rantingrick said:
Okay, then do some processing on the source. You can use regexps or
the module mentioned earlier by Chris.
I think I'm making this unnecessarily complicated. I had used
something like:

from spam import TestAddresses ## just for grins

Which is something that I almost never do in practice.

Also, you pointed out the UC naming convention, which I was
unacquainted with, being self-employed, self-taught and a one-man
crew who doesn't spend as much time as he should reading PEPs.

I'm going to go for the predicate test as second argument to
getmembers with something like:
def isdata(self,obj,name):
"""Check if an object is of a type that probably means it's data."""
return (not (inspect.ismodule(obj) or inspect.isclass(obj) or
inspect.isroutine(obj) or inspect.isframe(obj) or
inspect.istraceback(obj) or inspect.iscode(obj)))
and name.issupper()
## Untested code

thanks again
 
S

Steven D'Aprano

Tim said:
dir(<targetmodule>) will also show globals from other modules imported
by the target module. So I would need a way to distinguish between
those imported and those defined in <targetmodule>

Why would you want to do that? Importing *is* a definition in
<targetmodule>.

Consider these two code snippets:

#1
from math import pi

#2
import math
tau = 2*math.pi
del math


Why do you think it is necessary to distinguish pi from tau? Both names are
local to the current namespace.


print(dir(targetmodule)) =>
['Install', 'TestAddresses', '__builtins__', '__doc__',
'__file__', '__name__', '__package__', 'chmod', 'consoleMessage',
'cp', 'debug', 'erh', 'exists', 'halt', 'is_list', 'load',
'makePath', 'mkdir', 'process', 'sys', 'traceback', 'usingCgi']
where 'TestAddresses' is a member of an imported module and

You are mistaken. TestAddresses is *not* a member of an imported module. It
is a member of the current module, which may or may not happen to point to
the same object as the other module as well.

'usingCgi' is the only data variable defined in <targetmodule>

It seems to me that your approach here is unnecessarily complex and fragile.
I don't know what problem you are trying to solve, but trying to solve it
by intraspecting differences that aren't differences is surely the wrong
way to do it.
 
T

Tim Johnson

* Steven D'Aprano said:
You are mistaken. TestAddresses is *not* a member of an imported module. It
is a member of the current module, which may or may not happen to point to
the same object as the other module as well.
You are correct. I mispoke or misapplied. See my last post.
It seems to me that your approach here is unnecessarily complex and fragile.
I don't know what problem you are trying to solve, but trying to solve it
by intraspecting differences that aren't differences is surely the wrong
way to do it.
See my last post...
 
S

Steven D'Aprano

Tim said:
See my last post...


Yes, but what are you actually *trying to do*? "Detecting data members" is
not an end in itself. Why do you think you need to detect data members?
 
T

Tim Johnson

* Steven D'Aprano said:
Yes, but what are you actually *trying to do*? "Detecting data members" is
not an end in itself. Why do you think you need to detect data members?

Steven, I'm building a documentation system. I have my own MVC framework
and the goal is to have a documentation module for each project.

Thanks again for the clarifications. I always learn a lot from
you.
 
C

Chris Angelico

 Steven, I'm building a documentation system. I have my own MVC framework
 and the goal is to have a documentation module for each project.

Is there a reason for not using Doxygen / Autodoc / etc, or at least
something in the same style? They work from specially-formatted
comments in the source code, rather than the compiled module object.

ChrisA
 
T

Tim Johnson

* Chris Angelico said:
Is there a reason for not using Doxygen / Autodoc / etc, or at least
something in the same style? They work from specially-formatted
comments in the source code, rather than the compiled module object.

I want this as a component of my system. It will be bound to a
relational data-structure-based 'core' that defines relationships
between all files in the project.

:) It's called *collateral*

And yes, I have worked with comment-based systems, including my
own, that worked with multi-language projects.

Best regards
 
I

Ian Kelly

 Steven, I'm building a documentation system. I have my own MVC framework
 and the goal is to have a documentation module for each project.

It sounds like what you really want is to detect the names *exported*
by the module, then. Why not do it the same way Python does it? If
the module defines an "__all__" attribute, then it is taken to be a
sequence of strings which are the exported names. Otherwise, the
exported names are taken to be all the names in the module dict that
don't begin with an underscore.

Cheers,
Ian
 
G

Grant Edwards

Is there a reason for not using Doxygen / Autodoc / etc, or at least
something in the same style? They work from specially-formatted
comments in the source code, rather than the compiled module object.

Because those specially-formatted comments are wrong.
 
T

Tim Johnson

* Ian Kelly said:
It sounds like what you really want is to detect the names *exported*
by the module, then. i Yes!
Why not do it the same way Python does it? If
the module defines an "__all__" attribute, then it is taken to be a
sequence of strings which are the exported names. Otherwise, the
exported names are taken to be all the names in the module dict that
don't begin with an underscore.

:) Oh here we go again. Another python feature I didn't know about
or have forgotten.

Thanks very much for that.
Good tip
 
G

Grant Edwards

:) Oh here we go again. Another python feature I didn't know about
or have forgotten.

You could probably implement at least two more languages using nothing
but Python features I don't know about or have forgotten. :)

Yet I still manage to get a lot accomplished using Python.
 
W

Waldek M.

Dnia Tue, 5 Jul 2011 14:11:56 +0000 (UTC), Grant Edwards napisa³(a):
Because those specially-formatted comments are wrong.

.... because?
Not in sarcasm mode; just curious why you don't like them.

Br.
Waldek
 
S

Steven D'Aprano

Waldek said:
Dnia Tue, 5 Jul 2011 14:11:56 +0000 (UTC), Grant Edwards napisał(a):

... because?
Not in sarcasm mode; just curious why you don't like them.

Because unless you are extremely disciplined, code and the comments
describing them get out of sync. Quote:

"At Resolver we've found it useful to short-circuit any doubt and just
refer to comments in code as 'lies'. "
--Michael Foord paraphrases Christian Muirhead on python-dev, 2009-03-22
 
G

Grant Edwards

Dnia Tue, 5 Jul 2011 14:11:56 +0000 (UTC), Grant Edwards napisa?(a):

... because?

In my experience, they're wrong because somebody changes the code and
not the comments.
Not in sarcasm mode; just curious why you don't like them.

There've been too many times when I couldn't trust them.
 
C

Chris Angelico

Because unless you are extremely disciplined, code and the comments
describing them get out of sync. Quote:

"At Resolver we've found it useful to short-circuit any doubt and just
refer to comments in code as 'lies'. "
--Michael Foord paraphrases Christian Muirhead on python-dev, 2009-03-22

And yet, as I have found out by trying to embed V8 (Google's
Javascript engine), those little comments can (a) prove the difference
between a bug and a misfeature, and (b) be all the documentation there
is. Okay, it's not QUITE the latter, but most things are not
documented outside of the source, and I greatly appreciate those
little comments!

ChrisA
 
W

Waldek M.

Dnia Wed, 06 Jul 2011 03:36:24 +1000, Steven D'Aprano napisa³(a):
Because unless you are extremely disciplined, code and the comments
describing them get out of sync. [...]
True, but that gets far worse with external docs.
Do you have in mind any better replacement?

Br.
Waldek
 

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

Staff online

Members online

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top