Printing a variable in an embedded Python interpre

2019-06-28 06:40发布

问题:

I have written a small C program that embeds Python. I'm setting it up correctly using Py_Initialize() and Py_Finalize(), and am able to run scripts either using PyRun_SimpleString or PyRun_SimpleFile. However, I don't know how mimic the behavior of Python's own interpreter when printing variables.

Specifically:

a = (1, 2, 3)
print a

Works fine for me: it prints out (1, 2, 3)

However:

a = (1, 2, 3)
a

Prints out nothing at all. In Python's own interpreter, this would print out (1, 2, 3) as well. How can I make my code do what users would expect and print out the value?

Thanks in advance!

回答1:

To run the interpreters interactive loop, you should use the function PyRun_InteractiveLoop(). Otherwise, your code will behave as if it were written in a Python script file, not entered interactively.

Edit: Here's the full code of a simple interactive interpreter:

#include <Python.h>

int main()
{
    Py_Initialize();
    PyRun_InteractiveLoop(stdin, "<stdin>");
    Py_Finalize();
}

Edit2: Implementing a full interactive interpreter in a GUI is a bit of a project. Probably the easiest way to get it right is to write a basic terminal emulator connected to a pseudo-terminal device, and use the above code on that device. This will automatically get all subtleties right.

If your aim isn't a full-blown interactive editor, an option might be to use PyRun_String() with Py_single_input as start token. This will allow you to run some Python code as in the interactive interpreter, and if that code happened to be a single expression that doesn't evaluate to None, a representation of its value is printed -- to stdout of course. Here is some example code (without error checking for simplicity):

#include <Python.h>

int main()
{
    PyObject *main, *d;
    Py_Initialize();
    main = PyImport_AddModule("__main__");
    d = PyModule_GetDict(main);
    PyRun_String("a = (1, 2, 3)", Py_single_input, d, d);
    PyRun_String("a", Py_single_input, d, d);
    Py_Finalize();
}

This will print (1, 2, 3).

There are still a lot of problems:

  • No error handling and traceback printing.
  • No "incremental input" for block commands like in the interactive interpreter. The input needs to be complete.
  • Output to stdout.
  • If multiple lines of input are given, nothing is printed.

To really replicate the behaviour of the interactive interpreter is not easy. That's why my initial recommendation was to write a basic terminal emulator in your GUI, which shouldn't be too hard -- or maybe there's even one available.