Why does the Python/C API crash on PyRun_SimpleFile?

Sion Sheevok picture Sion Sheevok · Sep 7, 2010 · Viewed 16.2k times · Source

I've been experimenting with embedding different scripting languages in a C++ application, currently I'm trying Stackless Python 3.1. I've tried several tutorials and examples, what few I can find, to try and run a simple script from an application.

Py_Initialize();

FILE* PythonScriptFile = fopen("Python Scripts/Test.py", "r");
if(PythonScriptFile)
{
    PyRun_SimpleFile(PythonScriptFile, "Python Scripts/Test.py");
    fclose(PythonScriptFile);
}

Py_Finalize();

For some odd reason, running this piece of code results in an access violation at:

    PyRun_SimpleFile(PythonScriptFile, "Python Scripts/Test.py");

I've searched online for others with a similar problem and found only one. Their only solution was a workaround that only seems possible in an older version of Python: Creating a python file object and returning the FILE* from that python file object into PyRun_SimpleFile. Such function calls are not available however, the Python 3.1 API creates file objects from a file descriptor and returns file descriptors, but the PyRun_SimpleFile function still requires a FILE*.

I'm at a loss as to how to run any scripts from file, short of loading the entire file into memory manually and running it as a giant string, certainly not a practical solution.

What gives? How can I accomplish this task if the API has an internal error?

Update: I've managed to build Stackless Python 3.1 from the source and yet the crash remains completely unchanged, despite using the same C runtime library. Both my project and the Stackless Python 3.1 source are built with Visual Studio 2010's C++ compiler and C runtime. I no longer have any inkling as to what might solve this problem, short of modifying Python to use a file name and not a FILE*. Another terrible workaround.

Answer

sambha picture sambha · Sep 14, 2011

I was getting a similar crash & did the below:

   PyObject* PyFileObject = PyFile_FromString("test.py", "r");
   PyRun_SimpleFileEx(PyFile_AsFile(PyFileObject), "test.py", 1);

Note that this was in python 2.7 though. I don't know if the API has changed in 3.x.