I have a C++ application dynamically linked to the Python interpreter. I want to be able to import python modules from a particular directory. I want to modify the PYTHONPATH for my process so that sys.path will include the paths that I added to the PYTHONPATH. That seems to be the way it works according to this documentation:
http://docs.python.org/c-api/intro.html#embedding-python
However, when I print sys.path from Python-land it has the original contents of PYTHONPATH and not the one I set. Here's an example of what I'm doing (using Boost.Python):
int main(int argc, char* argv[])
{
_putenv_s("PYTHONPATH", "C:\\source\\\\modules");
Py_Initialize();
object main = import("__main__");
object global = (main.attr("__dict__"));
exec("import sys\nprint sys.path"), global, global);
}
PS - I know there are other ways to accomplish my goal, but that's not what I'm asking about. I am wondering why Py_Initialize() doesn't use the current value of PYTHONPATH when setting up sys.path. Or perhaps I've misunderstood how it is supposed to work?
I found cross-platform solution. Before invoke any other python code just execute following python lines:
import sys
sys.path.append("C:\\source\\\\modules")
This happens if you're using more than one C runtime library at a time. In this case, your application and the Python DLL are probably linked against different CRTs. Each CRT has its own set of environment variables; changes to the environment made with putenv from one CRT are not visible from getenv calls made with a different CRT.
See the "readEnv" example at http://msdn.microsoft.com/en-us/library/ms235460%28v=vs.80%29.aspx.
You can fix this by making sure to use only a single CRT, but that's tricky in practice. Debug builds of programs typically use debug CRTs (which enable things like heap checks and API assertions); production DLLs, even when used in debugging, typically use MSVCRT, the production, threadsafe version. I've worked around this by disabling the debug CRTs entirely, setting all builds to "multithreaded dynamic", since maintaining separate debug DLLs is too much of a hassle. You lose some debugging capabilities by doing that.
Check out:
void PySys_SetPath(char *path) Set sys.path to a list object of paths found in path which should be a list of paths separated with the platform’s search path delimiter (: on Unix, ; on Windows).
or
Py_SetProgramName(argv[0]); That adds dirname(argv[0]) to your PYTHONPATH for you.
As other people have said, you may be running into a CRT mismatch. I was able to get this to work with Python 2.6 and Visual C++ 2008:
#include "stdafx.h"
#include "Python.h"
int _tmain(int argc, _TCHAR* argv[])
{
_putenv_s("PYTHONPATH", "C:\\source\\\\modules");
Py_Initialize();
PyRun_SimpleString("import sys\nprint sys.path");
PyRun_SimpleString("raw_input()");
return 0;
}
This output:
['C:\\Python26\\lib\\site-packages\\distribute-0.6.13-py2.6.egg', 'C:\\Python26\
\lib\\site-packages\\virtualenv-1.4.9-py2.6.egg', 'C:\\source\\modules', ...
Another option may be to change to that directory, since the current directory typically ends up on the path, e.g.:
_chdir("c:\\");
Py_Initialize();
[...]
which gives me:
['C:\\Python26\\lib\\site-packages\\distribute-0.6.13-py2.6.egg', 'C:\\Python26\
\lib\\site-packages\\virtualenv-1.4.9-py2.6.egg', 'C:\\Windows\\system32\\python
26.zip', 'C:\\Python26\\Lib', 'C:\\Python26\\DLLs', 'C:\\Python26\\Lib\\lib-tk',
'c:\\', ...
You could just do python3 -c "import sys; sys.path.append('C:\Path\To\Modules')"
It is possible that the Python DLL gets its own copy of the environment when it is loaded. Try loading it with LoadLibrary and GetProcAddress after you've changed the environment and see if that changes anything.
#include "Python.h"
int main()
{
Py_Initialize();
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append(\"<some_path>\")");
return 0;
}
This worked for all python version (2.6, 2.7, 3.1, 3.2, 3.3 and 3.4).
Several notes regarding <some_path>:
It should contain only a single directory. List of directories with valid separators (d:/path1;d:/path2 etc.) is not working
Windows paths like: d:\\path1 will work only for python versions prior to Python 3, for later versions d:\\\\path1 should be used. I'd advice replacing windows path delimiters with unix delimiters. Following code chunk does this.
std::string my_path = "<some_path>";
std::replace(my_path.begin(), my_path.end(), '\\', '/');
A gentle advise:
Don't waste your time trying to modify PYTHONPATH with either of the following API methods if you want to support different python versions:
Py_SetPythonHome() - for python 2 requires an ascii string, for python 3 - a unicode string, but doesn't work reliably for versions greater than 3.1
Py_SetPath() - introduced in python 3, but is buggy (see http://bugs.python.org/issue11320)
In general API methods listed above do not affect after Py_Initialize() call.
Related
I recently installed ldc through hombrew on my Mac and was testing out running a code as a script from the D wiki when I noticed that using ldmd2 to compile my program doesn't also run my program after. Whats the difference then since this is the same behavior as running ldc2.
Heres my program
import std.stdio;
void main()
{
writeln("Hello, world without explicit compilations!");
}
EDIT:
The website states "For small projects it's handy to compile and run in a single step. Most (if not all) compiler packages, contain a tool named rdmd/gdmd/ldmd or similar. For instructional purposes we'll call it rdmd." What im taking from this is it depends on which compiler your using but in the case of ldc I should be using ldmd.
ldmd2 is just a wrapper script for ldc2 which converts argument formats from dmd style over to ldc style.
So it does exactly the same thing, just some options and flags on the compile command line have different names and stuff like that.
The link is talking about rdmd which is a separate program that recursively grabs dependencies, compiles, and automatically runs. rdmd works on top of the compiler and might have been packaged with it or might need to be downloaded separately.
Its source lives here: https://github.com/D-Programming-Language/tools/blob/master/rdmd.d
and it is compatible with ldmd2's option formats.
I'm sure if it's possible, but I'd like to call the function which is defined in the exe file on Linux/Mac:
0x421ff0 ##my_func_doing_stuff#Initialize 4
Basically I'd like to add command line support which is not implemented and the UI is kind of drag&drop which is useless.
Note: I don't have access to the source of the file.
I've was playing with wine, objdump, uncc (trying to covert it into C again) and Python using pefile, SWIG and ctypes:
#!/usr/bin/python
from ctypes import *
import pefile, sys
pe = pefile.PE('my_file.exe')
print pe.dump_info()
my_exe = cdll.LoadLibrary('./my_file.exe')
but without success.
The error:
OSError: ./my_file.exe: invalid ELF header
reminded me that I can't call any of Windows functions under Linux without emulation?
So I'm looking for some other solutions. Probably it can be done somehow by emulating or debugging it under wine. But I'm not sure if there is any API for calling the specific functions.
Are there any existing solutions?
You can use winelib to load and link with the binary (since you need wine to provide a usable ABI), but keep in mind that this effectively turns your application into a Wine application.
Using Eclipse and CDT to debug C++ code the variable windows is cumbersome and not very informative for types defined in the standard template library or in boost (e.g. shared_ptr).
Just an example how this may look like for an std::vector:
bar {…}
std::_Vector_base<TSample<MyTraits>, std::allocator<TSample<MyTraits> > >
_M_impl {…}
std::allocator<TSample<MyTraits> > {…}
_M_start 0x00007ffff7fb5010
_M_finish 0x00007ffff7fd4410
_M_end_of_storage 0x00007ffff7fd5010
Even if this information about the internals of those types may be useful, in almost any cases I would expect a clearer presentation here, i.e. a list of values for the std::vector. Are there any tools, plugins or other modifications around which can do this?
EDIT
The following solutions does not work for linux. I am using ubuntu 14.04, eclipse, g++, gdb.
I cant find a package gdb-python and linux does not use mingw
You need a version of GDB capable of using python to pretty print structures. I know at least on windows using mingw that this is not provided in the default install.
Pretty Printers are python modules which tell gdb how to display a given structure. You can write your own, but there are already printers for STL available for download.
To Get Pretty Printers working on Windows (instructions should be similiar for other OS's):
Prerequisites
Make sure you have you have Python 2.7 installed and in the system path.
http://www.python.org/download/
Make sure MinGW-get is installed
http://sourceforge.net/projects/mingw/files/Installer/mingw-get-inst/
Make sure you have an SVN client are installed
Installation:
Open a command Shell and type:
mingw-get install gdb-python
When its finished cd to a local directory and install the printers by typing:
svn co svn://gcc.gnu.org/svn/gcc/trunk/libstdc++-v3/python
Open the .gdbinit (create it in a text editor if need be) and type the following replaceing "C:/directory" with the folder that you checked the printers into.
Python
import sys
sys.path.insert(0, 'C:/directory')
from libstdcxx.v6.printers import register_libstdcxx_printers
register_libstdcxx_printers (None)
end
Eclipse Setup
Go To Windows > Preferences > C/C++ > Debug > GDB
Where it Says GDB Debugger put the path to the python enabled GDB it will most likely be in the mingw /bin folder with a name like gdb-python27.exe
Where it says GDB Command File put the path to the .gdb init file you made earlier.
That's it, debug like normal, the stl structures should be much easier to read.
Well, gdb don't natively support STL containers. You can't say this is incorrect, since it will expose the inner workings of the STL objects, but most of the time it is not what we want, right?
If you're using gdb 7.0 you can take advantage of the pretty printers. This website http://sourceware.org/gdb/wiki/STLSupport has a pretty simple tutorial on how to set them. I copied below the part that interests you:
Check-out the latest Python libstdc++ printers to a place on your
machine. In a local directory, do:
svn co svn://gcc.gnu.org/svn/gcc/trunk/libstdc++-v3/python
Add the following to your ~/.gdbinit. The path needs to match
where the python module above was
checked-out. So if checked out to:
/home/maude/gdb_printers/, the path
would be as written in the example:
python
import sys
sys.path.insert(0, '/home/maude/gdb_printers/python')
from libstdcxx.v6.printers import register_libstdcxx_printers
register_libstdcxx_printers (None)
end
The path should be the only element
that needs to be adjusted in the
example above. Once loaded, STL
classes that the printers support
should printed in a more
human-readable format. To print the
classes in the old style, use the /r
(raw) switch in the print command
(i.e., print /r foo). This will print
the classes as if the Python
pretty-printers were not loaded.
Since you're using eclipse cdt, don't forget to point your debug configuration to your .gdbinit file. When creating a new Debug Configuration, go to the Debugger tab and put the path to the .gdbinit file in the "GDB command file" field.
I hope that helps!
In debug view in variables list expand vector:
"vector_name" -> std::_Vector_base<"datatype"> -> _M_impl
then right click on _M_start and select "Display as array...", type its length and then click OK. Now you can expand each item of your vector.
If you have gdb support for CDT (see, for example, GDB in Eclipse), you could try this: De-referencing STL containers
Long ago I also stumbled upon your same problem. It was a pain to check the STL containers. Then I found that link and added to my .gdbinit file some of those definitions. Life was easier after that.
NOTE: My gdb version is 7.1 and adding those definitions work fine. I don't know if in newer versions of gdb they are already included.
I would like to expand on the Windows 7 response because some key steps are left out:
This is for MinGW users with Eclipse CDT
0) If you don't have python GDB, open a shell/command and use MinGW-get.exe to 'install'
Python-enabled GDB e.g.
MinGw-get.exe install gdb-python
1a) Get Python 2.7.x from http://python.org/download/ and install
1b) Make sure PYTHONPATH and PYTHONHOME are set in your environment:
PYTHONPATH should be C:\Python27\Lib (or similar)
PYTHONHOME should be C:\Python27
1c) Add PYTHONHOME to your PATH
%PYTHONHOME%;...
2a) Open a text enter, enter the following statements. Notice the 3rd line is
pointing to where the python scripts are located. See notes below about this!
python
import sys
sys.path.insert(0, 'C:/MinGW/share/gcc-4.6.1/python')
from libstdcxx.v6.printers import register_libstdcxx_printers
register_libstdcxx_printers (None)
end
2b) Save as '.gdbinit' NOTE: Windows explorer will not let you name a file that starts with
with a period from explorer. Most text edits (including Notepad) will let you. GDB init
files are like 'scripts' of GDB commands that GBD will execute upon loading.
2c) The '.gdbinit' file needs to be in the working directory of GDB (most likely this is
your projects root directory but your IDE can tell you.
3) Open your Eclipse (or other IDE) Preferences dialog. Go to the C++ Debugger sub-menu.
4) Configure Eclipse to use C:\MinGW\bin\gdb-python27.exe as the debugger and your .gdbinit as the config file.
5a) Re-create all your debug launch configurations (delete the old one and create a new one from scratch).
--OR--
5b) Edit each debug configuration and point it to the new gdb-python.exe AND point it to the.
If you run into issues:
--Don't forget to change the location to the python directory in the above python code!
This directory is created by MinGW, so don't go looking to download the pretty printers, MinGW
did it for you in step zero. Just goto your MinGW install director, the share folder,
the GCC folder (has version number) and you will find python folder. This location is what
should be in python script loaded by GDB.
--Also, the .gdbinit is a PITA, make sure its named correctly and in the working folder of GDB
which isn't necessarily where gdb-python.exe is located! Look at your GDB output when loading GDB to see if a) 'python-enabled' appears during load and that the statements in the .gdbinit are appearing.
--Finally, I had alot of issues with the system variables. If python gives you 'ImportError' then most likely you have not set PYTHONPATH or PYTHONHOME.
--The directory with 'gdb-python27' (e.g. C:\MinGW\bin') should also be on your path and if it is, it makes setting up eclipse a bit nicer because you don't need to put in absolute paths. But still, sometimes the .gbdinit needs an absoulte path. if it works you'll see output from gbd (console->gdb traces) like this on startup of debugger:
835,059 4^done
835,059 (gdb)
835,059 5-enable-pretty-printing
835,069 5^done
....
835,129 12^done
835,129 (gdb)
835,129 13source C:\MinGW\bin\.gdbinit
835,139 &"source C:\\MinGW\\bin\\.gdbinit\n"
835,142 13^done
835,142 (gdb)
I know that JDT (Java environment in eclipse) provides custom "formatters" to be applied when displaying variable values in debug views. A quick look at google for the same in CDT brings this page:
http://wiki.eclipse.org/CDT/Better_Debugging_%28GSoC_project%29
I don't know if this has been yet integrated in the main CDT line, may be you can try to right click on a variable while debugging (in the last CDT) and see if there is a custom formater entry. If not available I recomend you to add a new tracker entry in CDT tracker to ask this enhancement.
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.
This works for me on Python 3:
PyObject *obj = Py_BuildValue("s", "test.py");
FILE *file = _Py_fopen_obj(obj, "r+");
if(file != NULL) {
PyRun_SimpleFile(file, "test.py");
}
I hope It would be useful.
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.
Your code works correctly on my installed version of Python 2.6. I also built stackless 3.1.2 from source and it worked correctly. This was with g++ 4.4.3 on Ubuntu 10.04. If you're on windows, you might want to check that both stackless and your code are built against the same C runtime.
This sounds like a problem of mismatched APIs. If your code and the Python runtime were compiled with different compilers, or even different compiler options, then accessing the FILE* could result in an access violation. Can you double-check that you've build your C code properly?
You mention that you're embedding Python into your C++ application. Keep in mind that Python is C code, compiled as C code. Perhaps that is the source of the problem?
If you built your test with VC 2010, you will definitely have problems - VC9 (VS 2008) and VC10 (VS 2010) have mutually incompatible support DLLs that are usually required (implement printf, file i/o and that sort of thing). You cannot mix them if they include the standard libraries, which the python build does.
You always have the option of using gcc (e.g. Cygwin or mingw) or downloading Visual Studio 2008 express, which should work fine for experimentation into python embedding. I have used both with the standard Python 2.7.6 build.
And what about this solution:
Py_SetProgramName(argv[0]);
Py_Initialize();
PyRun_SimpleString("execfile(\"ex30.py\")");
Py_Finalize();
Where ex30.py it the name of the python script I am running.
The below code will execute the test.py module. Python will search the module in the path set. So the path should be handled first.
Py_Initialize();
string path = "Python Scripts/";
//Set the path
PyRun_SimpleString("import sys");
string str = "sys.path.append('" + path + "')";
PyRun_SimpleString(str.c_str());
//Dont use test.py as it actually searches sub module test>>py
PyObject * moduleName = PyUnicode_FromString("test");
PyObject * pluginModule = PyImport_Import(moduleName);
if (pluginModule == nullptr)
{
PyErr_Print();
return "";
}
//Do the executions here
//clean up
Py_DECREF(moduleName);
Py_DECREF(pluginModule);
Py_DECREF(transformFunc);
Py_DECREF(result);
Py_Finalize();
I'm trying to embed python within a C++ based programming language (CCL: The compuatational control language, not that any of you have heard of it). Thus, I don't really have a "main" function to make calls from.
I have made a test .cc program with a main, and when I compile it and run it, I am able to import my own python modules and system modules for use.
When I embed my code in my CCL-based program and compile it (with g++), it seems I have most functionality, but I get a RUNTIME error:
ImportError: /usr/lib/python2.6/lib-dynload/_ctypes.so: undefined symbol: PyType_GenericNew
This is the code that is executed at Runtime error.
void FFSim::initCKBot (){
Py_Initialize();
PyRun_SimpleString("execfile('logical.py')");
}
logical.py imports modules, one of which attempts to execute 'from cytpes import *', which throws the runtime error.
Can someone explain this to me and how to go about solving it? It seems like I've linked the objects correctly when compiling the c++ aspect of the code.
Thanks.
The Python runtime is effectively a collection of libraries that your program uses. Those libraries take strings, convert them to Python bytecode and then interpret the bytecode. The error you're getting is that as part of interpreting the program, the Python runtime needs to call a function (PyType_GenericNew), but that function does not exist in the compiled Python runtime on your system. Going off the name of the function, this isn't something you can ignore or workaround. It's a fundamental part of the runtime.
Assuming your PATH is correct, your best solution is to reinstall or rebuild Python. Your installation is missing something important.