Connecting different Python interpreters
==========================================

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

Here we run a Python3 interpreter to connect to a Python2.6 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.6")
    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`.


    >>> import execnet
    >>> execnet.makegateway("popen//python=python3.1")
    <PopenGateway id='gw0' receive-live, 0 active channels>
    >>> gw=execnet.makegateway("popen//python=python3.1")
    >>> 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(isinstance(channel.receive(), bytes)")
    >>> ch.send('a')
    >>> ch.receive()
    False
    >>> gw.reconfigure(py2str_as_py3str=False)
    >>> ch = gw.remote_exec("channel.send(isinstance(channel.receive(), bytes)")
    >>> ch.send('a')
    >>> ch.receive()
    True


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


