简体   繁体   中英

Embedding Python with C++

Problem: Strange exception is thrown when embedding Python with C++.

Program:

bool embedd::execute_python(std::string location)
{
    if (std::ifstream(location))
    {
            const char* file_location = location.c_str();
            FILE* file_pointer;
            // Initialize the Python interpreter
            Py_Initialize();
            file_pointer = _Py_fopen(file_location, "r");
            // Run the Python file
            PyRun_SimpleFile(file_pointer, file_location);
            // Finalize the Python interpreter
            Py_Finalize();
        return true;
    }
    return false;
}

What does the above code snippet should do: The function should first check whether the passed argument is a valid location of the python file. If the file is present then it should execute the Python file.

Am I getting expected results: yes and no.

what is going wrong:

Test file 1:

print("Hello world")

Result : Successful execution and getting proper output

Test file 2:

from tkinter import *
root = Tk()
root.mainloop()

Result : Exception root = Tk() File "C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python35-32\\Lib\\tkinter__init__.py", line 1863, in init baseName = os.path.basename(sys.argv[0]) AttributeError: module 'sys' has no attribute 'argv'

Tested with some other file and found that when-ever we import modules(any) like tkinter, uuid, os etc similar exception gets thrown. on digging briefly about this the process monitor of my IDE told "Symbol file is not loaded" eg no symbol file loaded for tk86t.dll

Python Version : 3.5.2

Links which I do have referred: SO - 1 found the bug has been fixed from Python 2.3 here BUGS

On the one hand your test file 2 imports Tk which expects a valid command line (like eg for windows C:\\>python script.py -yourarguments ) for some reasons. On the other hand you embed python and thus don't have a command line. That's what python complains ("module 'sys' has no attribute 'argv'"). You should create a fake command line directly after Py_Initialize() with something like:

Py_Initialize();
wchar_t const *dummy_args[] = {L"Python", NULL};  // const is needed because literals must not be modified
wchar_t const **argv = dummy_args;
int             argc = sizeof(dummy_args)/sizeof(dummy_args[0])-1;
PySys_SetArgv(argc, const_cast<wchar_t **>(argv)); // const_cast allowed, because PySys_SetArgv doesn't change argv

Your test file 1 doesn't import Tk and thus doesn't expect a valid command line. That's the reason why it works without the code above.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM