[Python.NET] Embedding a Python interactive shell in a .NET application

Saparya K spryify at gmail.com
Fri May 27 17:40:59 EDT 2016


Just in case someone stumbles on this post looking for an answer:

A solution that worked for me was redirecting the Python stdout/stderr to a
stream in Python. I was then able to route this stream into the .NET text
box.

private void button1_Click(object sender, EventArgs e){
    using (Py.GIL())
    {
        // Redirect stdout to text box
        dynamic sys = PythonEngine.ImportModule("sys");

        string codeToRedirectOutput =
            "import sys\n" +
            "from io import StringIO\n" +
            "sys.stdout = mystdout = StringIO()\n" +
            "sys.stdout.flush()\n" +
            "sys.stderr = mystderr = StringIO()\n" +
            "sys.stderr.flush()\n";
        PythonEngine.RunString(codeToRedirectOutput);

        // Run Python code
        string pyCode = "print(1 + 2)";
        PyObject result = PythonEngine.RunString(pyCode); // null in
case of error
        if (result != null)
        {
            string pyStdout = sys.stdout.getvalue(); // Get stdout
            pyStdout = pyStdout.Replace("\n", "\r\n"); // To support
newline for textbox
            textBox1.Text = pyStdout;
        }
        else
        {
             PythonEngine.PrintError(); // Make Python engine print errors
             string pyStderr = sys.stderr.getvalue(); // Get stderr
             pyStderr = pyStderr.Replace("\n", "\r\n"); // To support
newline for textbox
             textBox1.Text = pyStderr;
        }
    }}

With this code, I was able to redirect the stdout (and stderr in the case
of an error) from the Python engine to a .NET text box.

On Wed, May 18, 2016 at 12:02 AM, Saparya K <spryify at gmail.com> wrote:

> Hi Denis,
> Thanks for pointing me to the new API. I am now able to embed Python in my
> C# code and access Python classes and methods from C#!
>
> Hi Nils,
> Your application looks very interesting and some of the features (e.g.
> matplotlib integration) are on the lines of what I have been thinking
> about. I am far from there though and will need to learn more before I can
> follow all the code in your wrapper!
>
> -----
>
> As of now, I am trying to redirect the output from the Python interpreter
> to a .NET text box. While I am able to redirect the output to a file, I am
> having trouble with routing the output to a text box.
>
> I first tried to redirect the console output to a custom TextWriter using
> Console.SetOut in C#:
>
> private void Form1_Load(object sender, EventArgs e)
> {
>     _writer = new TextBoxWriter(this.textBox1);
>     Console.SetOut(_writer);    // Redirect stdout to custom TextWriter
> that writes to the text box
> }
>
> This did not work: while output from C# is routed to the text box, output
> from Python is not.
>
> -----
>
> I then thought that maybe I need to redirect the Python stdout instead of
> the C# standard output. The idea was to assign Python's sys.stdout to a
> .NET object that implements the same interface as a python stream (write(),
> writelines()...):
>
> *.NET class to mimic Python stream:*
>
>    1.
>
>    public class TextBoxStream : PyObject // To assign to sys.stdout. Is this correct?{
>        private TextBox _output = null;
>
>        public TextBoxStream() {}
>
>        public TextBoxStream(TextBox output) {
>            _output = output;
>        }
>
>        void write(object value) {
>            _output.AppendText(value.ToString());
>        }}
>
>    *In Form1.cs:*
>
>    private void button1_Click(object sender, EventArgs e) {
>        using (Py.GIL())
>        {
>            // Redirect stdout to text box
>            dynamic sys = PythonEngine.ImportModule("sys");
>            TextBoxStream textBoxStream = new TextBoxStream(textBox1);
>            sys.stdout = textBoxStream; // This is probably not theright way?
>            //sys.SetAttr("stdout", textBoxStream); // This did not work either
>
>            string code =
>                "import sys\n" +
>                "print 'Message 1'\n" +
>                "sys.stdout.write('Message 2')\n" +
>                "sys.stdout.flush()";
>
>            PyObject redirectPyObj = PythonEngine.RunString(code); // returns NULL
>            sys.stdout.write("Message 3");
>            // Exception thrown: 'Python.Runtime.PyObject' does not contain a definition for 'stdout'
>        }}
>
>
> This does not work either: redirectPyObj is NULL. I tried using the old as
> well as the new Python.NET API (with dynamic). Neither the sys.stdout.write
> nor the print statements write to the text box.
>
> Any ideas on how to approach this would be very helpful.
> Thanks,
> Saparya
>
>
> On Tue, May 17, 2016 at 3:33 AM, Nils Becker <nilsc.becker at gmail.com>
> wrote:
>
>> Hey,
>>
>> a while ago I wrote something like a light wrapper around Python.NET to
>> embed CPython with numpy/scipy in a .NET GUI. It manages local/global
>> dictionaries, automatically converts simple data types and numpy
>> arrrays<->C# arrays and provides a plotting widget in C# that shows
>> matplotlib plots. It also has some other convenience functions.
>>
>> The code is by no means complete, fully tested or even nice. However, for
>> me it works.
>>
>> I uploaded it to github: https://github.com/Lodomir/PythonInterface
>> As it demonstrates some not-well documented use of Python.NET, I thought
>> it maybe nice to share the code.
>>
>> You will need to add the references to Python.NET to build the main
>> project (PythonInterface) and additionally to the PythonInterface-DLL to
>> build the examples.
>>
>> Cheers
>> Nils
>>
>> 2016-05-13 22:04 GMT+02:00 Denis Akhiyarov <denis.akhiyarov at gmail.com>:
>>
>>> for embedding look at c# embedding unit tests and also here:
>>>
>>> 1. Old API:
>>>
>>> http://pythonnet.github.io/readme.html
>>>
>>> 2. New simplified API using dynamic:
>>>
>>> https://github.com/pythonnet/pythonnet/blob/master/README.md
>>>
>>>
>>>
>>> On Thu, May 12, 2016 at 4:16 PM, Saparya K <spryify at gmail.com> wrote:
>>>
>>>> Thanks for your response, Denis.
>>>>
>>>> I had not come across Sho earlier. It looks very interesting. (If only
>>>> Python 3.x support was available, though it does look like they have added
>>>> support for their own math and visualization libraries).
>>>>
>>>> I am going over the demos and the unit tests and I was able to write a
>>>> simple console application to access .NET objects from Python. This is very
>>>> encouraging!
>>>> I am still figuring out how to embed Python code in my C# WinForms
>>>> application (instead of a console application).
>>>>
>>>> I will continue my experiments, but in the meantime if you or anyone
>>>> else has any ideas on how to redirect the result from the Python
>>>> interpreter (say, to a rich text box), I would love to hear them. That is
>>>> one part of the puzzle that is unclear to me.
>>>>
>>>> Thanks,
>>>> Saparya
>>>>
>>>> On Wed, May 11, 2016 at 4:01 PM, Denis Akhiyarov <
>>>> denis.akhiyarov at gmail.com> wrote:
>>>>
>>>>> This is definitely possible with WinForms or WPF. See the demo folder
>>>>> in pythonnet repo. One of the demo's is still in pull request.
>>>>>
>>>>> You should probably just try running previous IronPython attempts
>>>>> using pythonnet and report issues if any. Have a look at Sho from Microsoft.
>>>>>
>>>>> There is someone trying to embed ipython REPL using
>>>>> pythonnet/Excel-DNA or COM in Excel with Custom Task Pane (CTP) written
>>>>> in WinForms:
>>>>>
>>>>> https://groups.google.com/forum/#!topic/jupyter/CVht4orvQtc
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On Wed, May 11, 2016 at 4:44 PM, Saparya K <spryify at gmail.com> wrote:
>>>>>
>>>>>> Hello PythonNet,
>>>>>>
>>>>>> I am looking to embed a Python interactive (REPL) shell in a .NET
>>>>>> WinForms application.
>>>>>> This C# application displays a graphical visualization of some data.
>>>>>> Methods to manipulate the data in the C# application would be exposed via a
>>>>>> Python API.
>>>>>> The idea is to be able to interact with the data from the Python
>>>>>> shell via the API, and thereby updating the graphical view.
>>>>>>
>>>>>> Ideally, the shell should support any valid Python syntax that is
>>>>>> required to use the API. This would involve:
>>>>>>
>>>>>>    1. Querying a collection of data from the application via the
>>>>>>    Python API
>>>>>>    2. Then manipulating this collection in the Python shell
>>>>>>    3. Making API calls with the modified collection as an argument
>>>>>>
>>>>>> I came across a few examples where an interactive shell was developed
>>>>>> using IronPython. A limitation with this approach is the absence of *Python
>>>>>> 3.x* support (and other C-compiled libraries) in IronPython. For
>>>>>> this reason, I would prefer to use Python.NET if it is possible.
>>>>>>
>>>>>> Has anyone here tried something like this with Python.NET before?
>>>>>> Does it looks like what I am trying to achieve is feasible?
>>>>>>
>>>>>> Any direction would be very helpful!
>>>>>>
>>>>>> _________________________________________________
>>>>>> Python.NET mailing list - PythonDotNet at python.org
>>>>>> https://mail.python.org/mailman/listinfo/pythondotnet
>>>>>>
>>>>>
>>>>>
>>>>> _________________________________________________
>>>>> Python.NET mailing list - PythonDotNet at python.org
>>>>> https://mail.python.org/mailman/listinfo/pythondotnet
>>>>>
>>>>
>>>>
>>>> _________________________________________________
>>>> Python.NET mailing list - PythonDotNet at python.org
>>>> https://mail.python.org/mailman/listinfo/pythondotnet
>>>>
>>>
>>>
>>> _________________________________________________
>>> Python.NET mailing list - PythonDotNet at python.org
>>> https://mail.python.org/mailman/listinfo/pythondotnet
>>>
>>
>>
>> _________________________________________________
>> Python.NET mailing list - PythonDotNet at python.org
>> https://mail.python.org/mailman/listinfo/pythondotnet
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/pythondotnet/attachments/20160527/1d5e6857/attachment-0001.html>


More information about the PythonDotNet mailing list