PythonNet - how to populate __dict__ - ipython does, python doesn't

786 views Asked by At

When I load a .Net class from Python using PythonNet, it doesn't populate the python __ dict__ for the class, but when I load it from ipython using the same sequence of commands, it does. Can anyone say how to get the ipython behaviour from plain Python?

Many thanks.

python -c "import clr; clr.AddReference('System.Windows.Forms'); import System.Windows.Forms; print len(System.Windows.Forms.__dict__)"
3

ipython -c "import clr; clr.AddReference('System.Windows.Forms'); import System.Windows.Forms; print len(System.Windows.Forms.__dict__)"
714

I've tried this in python 2.7.11 and 3.5.2. Pythonnet 2.0.0 and 2.1.0. I believe I'm using CLR 4.0.30319 (this is installed along with others).

I presume ipython is doing some sort of introspection / reflection to find the members of the Forms class / module, perhaps for its completion / intellisense. How can I invoke this in regular Python?

Here's a longer version which prints the contents (as requested by denfromufa) - call the file TestPN.py:

import clr
clr.AddReference('System.Windows.Forms')
import System.Windows.Forms

nCount = 0
for s, o in System.Windows.Forms.__dict__.items():
    print(s, o, type(o))
    nCount += 1
    if nCount > 10:
        break

And the output from each:

ipython TestPN.py

SelectionRange <class 'System.Windows.Forms.SelectionRange'> <class 'CLR.CLR Metatype'>
PropertyGrid <class 'System.Windows.Forms.PropertyGrid'> <class 'CLR.CLR Metatype'>
DataGridViewCellStyleConverter <class 'System.Windows.Forms.DataGridViewCellStyleConverter'> <class 'CLR.CLR Metatype'>
PrintPreviewControl <class 'System.Windows.Forms.PrintPreviewControl'> <class 'CLR.CLR Metatype'>
BindingManagerDataErrorEventArgs <class 'System.Windows.Forms.BindingManagerDataErrorEventArgs'> <class 'CLR.CLR Metatype'>
KeyPressEventArgs <class 'System.Windows.Forms.KeyPressEventArgs'> <class 'CLR.CLR Metatype'>
TableLayoutPanelCellPosition <class 'System.Windows.Forms.TableLayoutPanelCellPosition'> <class 'CLR.CLR Metatype'>
TreeViewImageIndexConverter <class 'System.Windows.Forms.TreeViewImageIndexConverter'> <class 'CLR.CLR Metatype'>
DrawListViewSubItemEventArgs <class 'System.Windows.Forms.DrawListViewSubItemEventArgs'> <class 'CLR.CLR Metatype'>
ItemChangedEventArgs <class 'System.Windows.Forms.ItemChangedEventArgs'> <class 'CLR.CLR Metatype'>
ToolStripItemRenderEventArgs <class 'System.Windows.Forms.ToolStripItemRenderEventArgs'> <class 'CLR.CLR Metatype'>


python TestPN.py
__name__ System.Windows.Forms <class 'str'>
__doc__ Namespace containing types from the following assemblies:

- System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 <class 'str'>
__class__ <class 'CLR.ModuleObject'> <class 'type'>
__file__ C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Drawing\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Drawing.dll <class 'str'>

python --version
Python 3.5.2

ipython --version
5.1.0
1

There are 1 answers

0
Hagrid67 On

The answer is to use clr.setPreload(True)

import clr
clr.AddReference('System.Windows.Forms')
clr.setPreload(True)
import System.Windows.Forms
print(len(System.Windows.Forms.__dict__))

outputs:

714

...as desired.

It's a bit slower at the import statement, as you might expect.