Overview
The Very High Level Layer provides simple functions to execute Python code from C without detailed interaction with the interpreter. These functions accept Python source code as strings or files.
These functions use FILE* parameters. Ensure the FILE structures come from the same C runtime library as Python to avoid compatibility issues.
Running Python Code
From Strings
PyRun_SimpleString
int PyRun_SimpleString ( const char * command )
Execute Python code from a string in the __main__ module.
Python source code to execute
Returns: 0 on success, -1 if an exception was raised
Example:
int result = PyRun_SimpleString (
"import sys \n "
"print('Python version:', sys.version) \n "
);
if (result != 0 ) {
fprintf (stderr, "Failed to execute Python code \n " );
}
Unhandled SystemExit exceptions will exit the process (unless PyConfig.inspect is set).
From Files
PyRun_SimpleFile
int PyRun_SimpleFile (FILE * fp , const char * filename )
Execute Python code from a file.
Open file pointer to read Python code from
Filename for error messages (decoded from filesystem encoding)
Returns: 0 on success, -1 on error
Example:
FILE * fp = fopen ( "script.py" , "rb" ); // Binary mode on Windows!
if (fp == NULL ) {
perror ( "Failed to open script" );
return - 1 ;
}
int result = PyRun_SimpleFile (fp, "script.py" );
fclose (fp);
On Windows, open files in binary mode ("rb") to handle line endings correctly.
Interactive Execution
PyRun_InteractiveOne
int PyRun_InteractiveOne (FILE * fp , const char * filename )
Read and execute a single statement from an interactive device.
Interactive input source (typically stdin)
Filename for prompts and error messages
Returns:
0 - Input executed successfully
-1 - An exception occurred
Error code from errcode.h - Parse error
The user is prompted with sys.ps1 and sys.ps2.
PyRun_InteractiveLoop
int PyRun_InteractiveLoop (FILE * fp , const char * filename )
Read and execute statements until EOF, creating a Python REPL.
Returns: 0 at EOF, negative on failure
Example:
printf ( "Python Interactive Shell \n " );
PyRun_InteractiveLoop (stdin, "<stdin>" );
Advanced Execution
PyRun_String
PyObject * PyRun_String (
const char * str ,
int start ,
PyObject * globals ,
PyObject * locals
)
Execute Python code with specific namespace.
Python source code to compile and execute
Grammar start symbol (see Start Symbols below)
Global namespace dictionary
Local namespace (can be any mapping object)
Returns: Result of execution as PyObject*, or NULL on error
Example:
PyObject * main_module = PyImport_AddModule ( "__main__" );
PyObject * globals = PyModule_GetDict (main_module);
PyObject * locals = PyDict_New ();
PyObject * result = PyRun_String (
"x = 42 \n y = x * 2 \n y" ,
Py_file_input,
globals,
locals
);
if (result == NULL ) {
PyErr_Print ();
} else {
printf ( "Result: %ld \n " , PyLong_AsLong (result));
Py_DECREF (result);
}
Py_DECREF (locals);
Compilation
Py_CompileString
PyObject * Py_CompileString (
const char * str ,
const char * filename ,
int start
)
Compile Python source to a code object without executing.
Filename for error messages and tracebacks
Start symbol: Py_file_input, Py_eval_input, or Py_single_input
Returns: Code object, or NULL on error
Example:
PyObject * code = Py_CompileString (
"def hello(name): return f'Hello, {name}!'" ,
"<string>" ,
Py_file_input
);
if (code != NULL ) {
// Execute with PyEval_EvalCode
Py_DECREF (code);
}
PyEval_EvalCode
PyObject * PyEval_EvalCode (
PyObject * co ,
PyObject * globals ,
PyObject * locals
)
Execute a precompiled code object.
Code object from Py_CompileString
Global namespace dictionary
Local namespace dictionary
Start Symbols
Start symbols determine what kind of Python code can be compiled:
Single expression - returns the expression value Py_CompileString ( "2 + 2" , "<expr>" , Py_eval_input)
Sequence of statements - typical for modules/files Py_CompileString ( "x = 1 \n y = 2" , "<file>" , Py_file_input)
Single statement - used in interactive interpreters Py_CompileString ( "print('hello')" , "<stdin>" , Py_single_input)
Function type annotation - requires PyCF_ONLY_AST flag Used for parsing PEP 484 signature type comments.
Compiler Flags
Control compilation behavior with PyCompilerFlags:
typedef struct {
int cf_flags; // Compiler option flags
int cf_feature_version; // Python minor version for features
} PyCompilerFlags;
Common Flags
PyCF_ALLOW_TOP_LEVEL_AWAIT - Allow await at module level
PyCF_ONLY_AST - Return AST instead of code object
PyCF_TYPE_COMMENTS - Enable PEP 484 type comments
Example:
PyCompilerFlags flags = { 0 };
flags.cf_flags = PyCF_ALLOW_TOP_LEVEL_AWAIT;
flags.cf_feature_version = PY_MINOR_VERSION;
PyObject * result = PyRun_StringFlags (
"await asyncio.sleep(1)" ,
Py_file_input,
globals,
locals,
& flags
);
Customize interactive input behavior:
int ( * PyOS_InputHook)( void )
Function called when the interpreter becomes idle waiting for input. Useful for integrating with GUI event loops.
Example:
int my_input_hook ( void ) {
// Process GUI events
process_events ();
return 0 ;
}
PyOS_InputHook = my_input_hook;
PyOS_ReadlineFunctionPointer
char * ( * PyOS_ReadlineFunctionPointer)(FILE * , FILE * , const char * )
Override line reading function for interactive input.
Example:
char * my_readline (FILE * stdin , FILE * stdout , const char * prompt ) {
if (prompt)
fprintf (stdout, " %s " , prompt);
char * buffer = ( char * ) PyMem_RawMalloc ( 1024 );
if ( fgets (buffer, 1024 , stdin) == NULL ) {
PyMem_RawFree (buffer);
return NULL ;
}
return buffer;
}
PyOS_ReadlineFunctionPointer = my_readline;
See Also
Introduction C API basics and setup
Import Modules Import and use Python modules
Exception Handling Handle execution errors
Utilities Argument parsing and utilities