#include <stdio.h>
#include <Python.h>
int main(int argc, char *argv[]){
printf("line %d\n", __LINE__);
Py_Initialize();
printf("line %d\n", __LINE__);
Py_Main(argc, argv);
printf("line %d\n", __LINE__);
Py_Finalize();
printf("line %d\n", __LINE__);
return 0;
}
When I run the resulting binary I get the following....
$ ./embedded_python
line 5
line 7
Python 2.7.1 (r271:86832, Mar 25 2011, 11:56:07)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-48)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print 'hi'
hi
>>> exit()
I never see line 9 or 11 printed.
I need to embed python in an application that needs to do some cleanup
at the end so I need that code to execute.
What am I doing wrong?
Is there something else I should call besides "exit()" from within the
interpreter?
Is there something other than Py_Main that I should be calling?
Thanks,
~Eric
It must be a bug then that the exit() function doesn't do the same thing.
The documentation says "The return value will be the integer passed to
the sys.exit() function" but clearly nothing is returned since the
call to Py_Main exits rather than returning (even when calling
sys.exit instead of just exit).
In the mean time is there a way to redefine the exit function in
Python to do the same behavior as "ctrl-d?"
I realize that in doing that (if its even possible) still won't
provide a way to pass a value back from the interpreter via sys.exit.
Thanks,
~Eric
setvbuf(stdout, NULL, _IONBF, 0);
I think ctrl-d just causes sys.stdin to see EOF, so things just "fall
out" as you desire. exit() will winf up causing the C exit() function
after finalizing, hence the behaviour you see.
> In the mean time is there a way to redefine the exit function in
> Python to do the same behavior as "ctrl-d?"
You can just patch exit in builtins with your own function although I'm
not sure how you would terminate the builtin REPL - another alternative
may be to look into the code/console modules where you may be able to
arrange for more control over the REPL.
Cheers,
Mark
Are you sure that calling the builtin exit() function is the same as
calling sys.exit()?
You keep talking about the documentation for sys.exit(), but that's
not the function you're calling. I played around in the interactive
interpreter a bit, and the two functions do seem to behave a bit
differently from each other. I can't seem to find any detailed
documentation for the builtin exit() function though, so I'm not sure
exactly what the differences are.
A little more digging reveals that the builtin exit() function is
getting set up by site.py, and it does more than sys.exit() does.
Particularly, in 3.1 it tries to close stdin then raises SystemExit().
Does that maybe explain the behavior you're seeing? I didn't go
digging in 2.7, which appears to be what you're using, but I think you
need to explore the differences between sys.exit() and the builtin
exit() functions.
--
Jerry
http://docs.python.org/c-api/veryhigh.html?highlight=py_main#Py_Main
This C function never returns anything whether in the interpreter I
type "exit(123)" or "sys.exit(123)".
I cannot call any of my C cleanup code because of this.
Does PyRun_InteractiveLoop also have this problem?
I think there is a bug in that documentation - the paragraph:
Note that if an otherwise unhandled SystemError is raised, this
function will not return 1, but exit the process, as long as
Py_InspectFlag is not set.
Looks like it should refer to SystemExit, not SystemError. If you check
out pythonrun.c in handle_system_exit, you will note the behaviour
described above is exactly what is implemented for SystemExit.
See also http://bugs.python.org/issue6498
HTH,
Mark.
I don't want to pass a file. I want to run some C code, start an
interactive session, then run some more C code once the session is
over, but I cannot find a way to start an interactive Python session
within C that won't exit pre-maturely before I have a chance to run my
cleanup code in C.
Passing NULL as the 2nd parameter causes the segfault. Do this instead:
FILE* fp = stdin;
char *filename = "Embedded";
PyRun_InteractiveLoop(fp, filename);
See here regarding the segfault:
Instead of calling Py_Main, arrange for the following code to be executed:
import code
try:
code.interact()
except SystemExit:
pass
print "Done!"
If you save that as a script and run it, you will see that when you call
quit() or use Ctrl+D, the "Done!" is printed (so the exception is
caught) and things will return normally (albeit without any return code
that may have been specified in the SystemExit exception). If you
arrange to call that code in your app (either by importing it as a
module of even by calling PyRun_SimpleString) things should work as you
need.
HTH,
Mark