4

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!

Amro
  • 123,847
  • 25
  • 243
  • 454
FizzBuzz
  • 764
  • 6
  • 16
  • You need to simulate the interpreter then. Just evaluate the input line by line and `print` the results. – Niklas B. Mar 02 '12 at 22:40

1 Answers1

8

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.

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • Yes, I had tried this, but it seemed to want an interactive input - unless I was doing something wrong. What I tried was: FILE *myfile = fopen("example.py","r+"); PyRun_InteractiveLoop(myfile, "example.py"); fclose(myfile); – FizzBuzz Mar 02 '12 at 22:54
  • @FizzBuzz: So you want to read commands from a file, but want them behave as if they were interactively entered? And you claim this is what your users expect? I'm sure I'm missing something here. – Sven Marnach Mar 02 '12 at 23:01
  • @FizzBuzz: Note that the file you pass to `PyRun_InteractiveLoop()` must be "associated with an interactive device", as the linked documentation says. – Sven Marnach Mar 02 '12 at 23:02
  • You're right; I'm just not being clear - sorry! My initial test app is on the terminal; it would be trivial to point Python at stdin and let it work. However, I would like to take it into a GUI, which should behave to the user the same way but is not so easily hooked up. I'd like to read user input from somewhere (not stdin; a GUI text box), and have it executed in the same way as the command-line interpreter. Originally I was using PyRun_SimpleString() to send each line, but I also tried writing commands to a file and running from there. I hope this is clearer; thank you for your patience! – FizzBuzz Mar 02 '12 at 23:17
  • @FizzBuzz: Yes, that was really clear! Thanks, I'll update my answer. What platform are you on? – Sven Marnach Mar 02 '12 at 23:21
  • I'm using a Mac right now, but I'm thinking of writing something targeting either Android or iPhone depending on how things go. – FizzBuzz Mar 02 '12 at 23:25
  • @FizzBuzz: I got distracted, but I found the time to answer now. – Sven Marnach Mar 03 '12 at 00:22
  • Your second edit gives me more than enough to get started with - thank you! – FizzBuzz Mar 03 '12 at 00:23