File: hybridpython.rst

package info (click to toggle)
execnet 2.1.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 684 kB
  • sloc: python: 5,244; makefile: 78; sh: 2
file content (153 lines) | stat: -rw-r--r-- 4,844 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
Connecting different Python interpreters
==========================================

.. _`dumps/loads examples`:

Dumping and loading values across interpreter versions
----------------------------------------------------------

.. versionadded:: 1.1

Execnet offers a new safe and fast :ref:`dumps/loads API` which you
can use to dump builtin python data structures and load them
later with the same or a different python interpreter (including
between Python2 and Python3).  The standard library offers
the pickle and marshal modules but they do not work safely
between different interpreter versions.  Using xml/json
requires a mapping of Python objects and is not easy to
get right.  Moreover, execnet allows to control handling
of bytecode/strings/unicode types. Here is an example::

    # using python2
    import execnet
    with open("data.py23", "wb") as f:
        f.write(execnet.dumps(["hello", "world"]))

    # using Python3
    import execnet
    with open("data.py23", "rb") as f:
        val = execnet.loads(f.read(), py2str_as_py3str=True)
    assert val == ["hello", "world"]

See the :ref:`dumps/loads API` for more details on string
conversion options.  Please note, that you can not dump
user-level instances, only builtin python types.

Connect to Python2/Numpy from Python3
----------------------------------------

Here we run a Python3 interpreter to connect to a Python2.7 interpreter
that has numpy installed. We send items to be added to an array and
receive back the remote "repr" of the array::

    import execnet
    gw = execnet.makegateway("popen//python=python2.7")
    channel = gw.remote_exec("""
        import numpy
        array = numpy.array([1,2,3])
        while 1:
            x = channel.receive()
            if x is None:
                break
            array = numpy.append(array, x)
        channel.send(repr(array))
    """)
    for x in range(10):
        channel.send(x)
    channel.send(None)
    print (channel.receive())

will print on the CPython3.1 side::

    array([1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

A more refined real-life example of python3/python2 interaction
is the anyvc_ project which uses version-control bindings in
a Python2 subprocess in order to offer Python3-based library
functionality.

.. _anyvc: http://bitbucket.org/RonnyPfannschmidt/anyvc/overview/


Reconfiguring the string coercion between python2 and python3
-------------------------------------------------------------

Sometimes the default configuration of string coercion (2str to 3str, 3str to 2unicode)
is inconvient, thus it can be reconfigured via `gw.reconfigure` and `channel.reconfigure`. Here is an example session on a Python2 interpreter::


    >>> import execnet
    >>> execnet.makegateway("popen//python=python3.2")
    <Gateway id='gw0' receive-live, 0 active channels>
    >>> gw=execnet.makegateway("popen//python=python3.2")
    >>> gw.remote_exec("channel.send('hello')").receive()
    u'hello'
    >>> gw.reconfigure(py3str_as_py2str=True)
    >>> gw.remote_exec("channel.send('hello')").receive()
    'hello'
    >>> ch = gw.remote_exec('channel.send(type(channel.receive()).__name__)')
    >>> ch.send('a')
    >>> ch.receive()
    'str'
    >>> ch = gw.remote_exec('channel.send(type(channel.receive()).__name__)')
    >>> ch.reconfigure(py2str_as_py3str=False)
    >>> ch.send('a')
    >>> ch.receive()
    u'bytes'


Work with Java objects from CPython
----------------------------------------

Use your CPython interpreter to connect to a `Jython 2.5.1`_ interpreter
and work with Java types::

    import execnet
    gw = execnet.makegateway("popen//python=jython")
    channel = gw.remote_exec("""
        from java.util import Vector
        v = Vector()
        v.add('aaa')
        v.add('bbb')
        for val in v:
            channel.send(val)
    """)

    for item in channel:
        print (item)

will print on the CPython side::

    aaa
    bbb

.. _`Jython 2.5.1`: http://www.jython.org

Work with C# objects from CPython
----------------------------------------

(Experimental) use your CPython interpreter to connect to a IronPython_ interpreter
which can work with C# classes.  Here is an example for instantiating
a CLR Array instance and sending back its representation::

    import execnet
    gw = execnet.makegateway("popen//python=ipy")

    channel = gw.remote_exec("""
        import clr
        clr.AddReference("System")
        from System import Array
        array = Array[float]([1,2])
        channel.send(str(array))
    """)
    print (channel.receive())

using Mono 2.0 and IronPython-1.1 this will print on the CPython side::

    System.Double[](1.0, 2.0)

.. note::
   Using IronPython needs more testing, likely newer versions
   will work better.  please feedback if you have information.

.. _IronPython: http://ironpython.net