On 14/03/2017, Steven D'Aprano wrote:
But you do not need exec here at all. exec is a very powerful command,
but you should treat it as for experts only. Instead of writing:

     exec("qqq = inspect.getmembers(xModel.%s)" % x)

a much safer way is:

     qqq = inspect.getmembers(getattr(xModel, x))

which is faster, easier to understand, and easier to debug.

I also see you have not one, but two bare except clauses:

     try:
         ...
     except:
         ...


This is not a good idea! Please read this:

https://realpython.com/blog/python/the-most-diabolical-python-antipattern/


I think your code is too complex. Here is a simpler function which does
what you describe as "correct behaviour":

def esplora(xModel):
     i = 0
     for i, name in enumerate(dir(xModel), 1):
         what = type(getattr(xModel, name))
         print(name, what)
     print("Totale elementi: %s" % i)

and Peter Otten wrote:
I think the underlying problem is that Python 3 doesn't give you write
access to the function's namespace:

def f():
...     x = "a"
...     exec("print(x); x = 'b'; print(x)")
...     print(x)
...
f()
a
b
a

Here exec()'s namespace is initialized with a copy of the local namespace
whereas on the module level where global and local namespace are identical
it operates directly on the module namespace:

x = "a"
exec("print(x); x = 'b'; print(x)")
a
b
x
'b'

While exec() is the wrong choice in most cases (Steven already proposed a
better way to solve your problem) you can see the rebound names if you pass
a namespace explicitly:

def f():
...     ns = dict(x="a")
...     exec("print(x); x = 'b'; print(x)", ns)
...     print(ns["x"])
...
f()
a
b
b


First of all, many thanks to both of you, Steven and Peter!

Steven taught me how to use getattr() instead of directly inspecting the results of dir(), thus leading me unlock the inner structure of the document I'm exploring; Peter solved the puzzle I stumbled on while searching, and taught me something about function namespace.

As to the use of exec() and bare except, Steven, I read the post you linked some time ago, and I thoroughly understand those are very dangerous and complex commands. But I think I used them with all due caution.

Due to my ignorance about getattr(), I tried first using type(name) and later with inspect.getmembers(name), but both of them only applied to the string I gave them, instead of its meaning. That's why I felt forced to use exec. And it worked, while in the interpreter. I'm happy I did, because this made me learn something from you! (well, after a full weekend spent in failing efforts... ;-) )

As to the two bare excepts, I just don't care what the exception is, I'm only interested in knowing if there has been one, and I properly signalled it. So I think this is a proper use case for a bare except.

The output of dir(XSCRIPTCONTEXT.getDocument()), my real problem, is 290 items long, and some of them (e.g. the first one, "AllVersions") cannot be accessed at all. So I always get at least one exception, but I just don't care of them.

After your help, I modified my routine, still using a bare except:

# ---------------------------------------------------------------------------

# this only works as a Python macro called from LibreOffice
xModel = XSCRIPTCONTEXT.getDocument()
i = 0
questi = []
for i, name in enumerate(dir(xModel), 1):
    try:
        qqq = inspect.getmembers(getattr(xModel, name))
    except:
        qqq = "-NO AVAIL-"
    questi.append(str((name, qqq))+"\n")
questi.append(str(("Totale elementi:", " %s" % i)))
resultstring = "\n\n".join(questi)

# ---------------------------------------------------------------------------

and the first lines of its much awaited output:

=============================================================

('AllVersions', '-NO AVAIL-')

...

('Args', [('__add__', <method-wrapper '__add__' of tuple object at 0x7f2d18934048>), ('__class__', <class 'tuple'>), ('__contains__', <method-wrapper '__contains__' of tuple object at 0x7f2d18934048>), ('__delattr__', <method-wrapper '__delattr__' of tuple object at 0x7f2d18934048>), ('__dir__', <built-in method __dir__ of tuple object at 0x7f2d18934048>), ('__doc__', "tuple() -> empty tuple\ntuple(iterable) -> tuple initialized from iterable's items\n\nIf the argument is a tuple, the return value is the same object."), ('__eq__', <method-wrapper '__eq__' of tuple object at 0x7f2d18934048>), ('__format__', <built-in method __format__ of tuple object at 0x7f2d18934048>), ('__ge__', <method-wrapper '__ge__' of tuple object at 0x7f2d18934048>), ('__getattribute__', <method-wrapper '__getattribute__' of tuple object at 0x7f2d18934048>), ('__getitem__', <method-wrapper '__getitem__' of tuple object at 0x7f2d18934048>), ('__getnewargs__', <built-in method __getnewargs__ of tuple object at 0x7f2d18934048>), ('__gt__', <method-wrapper '__gt__' of tuple object at 0x7f2d18934048>), ('__hash__', <method-wrapper '__hash__' of tuple object at 0x7f2d18934048>), ('__init__', <method-wrapper '__init__' of tuple object at 0x7f2d18934048>), ('__iter__', <method-wrapper '__iter__' of tuple object at 0x7f2d18934048>), ('__le__', <method-wrapper '__le__' of tuple object at 0x7f2d18934048>), ('__len__', <method-wrapper '__len__' of tuple object at 0x7f2d18934048>), ('__lt__', <method-wrapper '__lt__' of tuple object at 0x7f2d18934048>), ('__mul__', <method-wrapper '__mul__' of tuple object at 0x7f2d18934048>), ('__ne__', <method-wrapper '__ne__' of tuple object at 0x7f2d18934048>), ('__new__', <built-in method __new__ of type object at 0x7f2d191dcc50>), ('__reduce__', <built-in method __reduce__ of tuple object at 0x7f2d18934048>), ('__reduce_ex__', <built-in method __reduce_ex__ of tuple object at 0x7f2d18934048>), ('__repr__', <method-wrapper '__repr__' of tuple object at 0x7f2d18934048>), ('__rmul__', <method-wrapper '__rmul__' of tuple object at 0x7f2d18934048>), ('__setattr__', <method-wrapper '__setattr__' of tuple object at 0x7f2d18934048>), ('__sizeof__', <built-in method __sizeof__ of tuple object at 0x7f2d18934048>), ('__str__', <method-wrapper '__str__' of tuple object at 0x7f2d18934048>), ('__subclasshook__', <built-in method __subclasshook__ of type object at 0x7f2d191dcc50>), ('count', <built-in method count of tuple object at 0x7f2d18934048>), ('index', <built-in method index of tuple object at 0x7f2d18934048>)])


('AutoStyles', [('CharacterStyles', pyuno object (com.sun.star.style.XAutoStyleFamily)0x7f2d30765c00{, supportedInterfaces={com.sun.star.style.XAutoStyleFamily,com.sun.star.lang.XTypeProvider,com.sun.star.uno.XWeak}}), ('Count', 3), ('ElementNames', ('CharacterStyles', 'RubyStyles', 'ParagraphStyles')), ('ElementType', <Type instance com.sun.star.style.XAutoStyleFamily (<Enum instance com.sun.star.uno.TypeClass ('INTERFACE')>)>), ('ImplementationId', <ByteSequence instance 'b'''>), ('ParagraphStyles', pyuno object (com.sun.star.style.XAutoStyleFamily)0x7f2d30765b20{, supportedInterfaces={com.sun.star.style.XAutoStyleFamily,com.sun.star.lang.XTypeProvider,com.sun.star.uno.XWeak}}), ('RubyStyles', pyuno object (com.sun.star.style.XAutoStyleFamily)0x7f2cf6ad3f20{, supportedInterfaces={com.sun.star.style.XAutoStyleFamily,com.sun.star.lang.XTypeProvider,com.sun.star.uno.XWeak}}), ('Types', (<Type instance com.sun.star.style.XAutoStyles (<Enum instance com.sun.star.uno.TypeClass ('INTERFACE')>)>, <Type instance com.sun.star.lang.XTypeProvider (<Enum instance com.sun.star.uno.TypeClass ('INTERFACE')>)>, <Type instance com.sun.star.uno.XWeak (<Enum instance com.sun.star.uno.TypeClass ('INTERFACE')>)>)), ('getByIndex', <PyUNO_callable object at 0x7f2d18a727b0>), ('getByName', <PyUNO_callable object at 0x7f2d18a727c8>), ('getCount', <PyUNO_callable object at 0x7f2d18a727e0>), ('getElementNames', <PyUNO_callable object at 0x7f2d18a727f8>), ('getElementType', <PyUNO_callable object at 0x7f2d18a72810>), ('getImplementationId', <PyUNO_callable object at 0x7f2d18a72828>), ('getTypes', <PyUNO_callable object at 0x7f2d18a72840>), ('hasByName', <PyUNO_callable object at 0x7f2d18a72858>), ('hasElements', <PyUNO_callable object at 0x7f2d18a72870>), ('queryAdapter', <PyUNO_callable object at 0x7f2d18a72888>), ('queryInterface', <PyUNO_callable object at 0x7f2d18a728a0>)])

...

('Totale elementi:', ' 290')

======================================================

Now I just have to search these 290 haystacks to find the fields I created in this form... but at least I have a magnifying glass.

THANKS !

Francesco
_______________________________________________
Tutor maillist  -  [email protected]
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Reply via email to