СПОЙЛЕР: частично решено (см. в конце).
Вот пример кода, использующего встроенный Python:
#include <Python.h>
int main(int argc, char** argv)
{
Py_SetPythonHome(argv[1]);
Py_Initialize();
PyRun_SimpleString("print \"Hello !\"");
Py_Finalize();
return 0;
}
Я работаю под Linux openSUSE 42.2 с gcc 4.8.5 (но у меня такая же проблема и на openSUSE 13.2 с gcc 4.8.3 или RedHat 6.4 с gcc 4.4.7).
Я скомпилировал статическую и динамическую версии Python 2.7.9 (но у меня такая же проблема с Python 2.7.13).
Я компилирую свой пример со ссылкой на статическую версию Python с помощью следующей команды:
g++ hello.cpp -o hello \
-I /home/caduchon/softs/python/2.7.9/64/gcc/4.8.5/static/include/python2.7 \
-L /home/caduchon/softs/python/2.7.9/64/gcc/4.8.5/static/lib \
-l python2.7 -l pthread -l util -l dl
Если я выполняю свой пример со статической версией Python в качестве аргумента, он работает.
Если я выполняю его на динамической версии Python в качестве аргумента, я получаю следующую ошибку (это происходит в Py_Initialize()
):
> ./hello /home/caduchon/softs/python/2.7.9/64/gcc/4.8.5/dynamic
Fatal Python error: PyThreadState_Get: no current thread
Aborted (core dumped)
Я понятия не имею, почему это работает со статической версией, а с динамической - нет. Как я могу решить такую проблему?
EDIT: мой сценарий установки Python выглядит следующим образом:
#!/bin/bash
WORKDIR=/home/caduchon/tmp/install_python_2sys.path
13
ARCHIVEDIR=/home/caduchon/downloads/python
PYTHON_VERSION='2.7.13'
EZ_SETUP_VERSION='0.9'
SETUPTOOLS_VERSION='34.1.0'
CYTHON_VERSION='0.25.2'
NUMPY_VERSION='1.12.0'
SCIPY_VERSION='0.18.1'
MATPLOTLIB_VERSION='2.0.0'
INSTALLDIR=/home/caduchon/softs/python/$PYTHON_VERSION/64/gcc/4.8.5
LAPACKDIR=/home/caduchon/softs/lapack/3.6.1/64/gcc/4.8.5
### Tkinter ###
echo "Install Tkinter"
sudo apt-get install tk-dev
### Workdir ###
echo "Create workdir"
mkdir -p $WORKDIR/static
mkdir -p $WORKDIR/dynamic
### Python
for x in static dynamic
do
echo "Install Python ($x)"
cd $WORKDIR/$x
echo " extract archive"
cp $ARCHIVEDIR/Python-$PYTHON_VERSION.tgz .
tar -xzf ./Python-$PYTHON_VERSION.tgz &> archive.log
cd ./Python-$PYTHON_VERSION
echo " configure"
if [ "$x" = "static" ]
then
./configure --prefix=$INSTALLDIR/$x --libdir=$INSTALLDIR/$x/lib &> configure.log
else
export LD_RUN_PATH=$INSTALLDIR/$x/lib
./configure --enable-shared --prefix=$INSTALLDIR/$x --exec-prefix=$INSTALLDIR/$x --libdir=$INSTALLDIR/$x/lib &> configure.log
fi
echo " build"
make &> make.log
echo " install"
make install &> make_install.log
echo " done"
done
### setuptools
for x in static dynamic
do
echo "Install setuptools ($x)"
cd $WORKDIR/$x
echo " extract archives"
cp $ARCHIVEDIR/ez_setup-$EZ_SETUP_VERSION.tar.gz .
tar -xzf ./ez_setup-$EZ_SETUP_VERSION.tar.gz &> archive.log
cp $ARCHIVEDIR/setuptools-$SETUPTOOLS_VERSION.zip .
unzip ./setuptools-$SETUPTOOLS_VERSION.zip &> archive.log
cp ./ez_setup-$EZ_SETUP_VERSION/ez_setup.py ./setuptools-$SETUPTOOLS_VERSION/.
cd ./setuptools-$SETUPTOOLS_VERSION
echo " install"
$INSTALLDIR/$x/bin/python ./ez_setup.py &> setup.log
echo " done"
done
### Cython
for x in static dynamic
do
echo "Install Cython ($x)"
cd $WORKDIR/$x
echo " extract archive"
cp $ARCHIVEDIR/Cython-$CYTHON_VERSION.tar.gz .
tar -xzf ./Cython-$CYTHON_VERSION.tar.gz &> archive.log
cd ./Cython-$CYTHON_VERSION
echo " install"
$INSTALLDIR/$x/bin/python ./setup.py install &> install.log
echo " done"
done
### NumPy
for x in static dynamic
do
echo "Install NumPy ($x)"
cd $WORKDIR/$x
echo " extract archive"
cp $ARCHIVEDIR/numpy-$NUMPY_VERSION.zip .
unzip ./numpy-$NUMPY_VERSION.zip &> archive.log
cd ./numpy-$NUMPY_VERSION
echo " build"
$INSTALLDIR/$x/bin/python ./setup.py build --fcompiler=gfortran &> build.log
echo " install"
$INSTALLDIR/$x/bin/python ./setup.py install &> install.log
echo " done"
done
### SciPy
for x in static dynamic
do
echo "Install SciPy ($x)"
cd $WORKDIR/$x
echo " extract archive"
cp $ARCHIVEDIR/scipy-$SCIPY_VERSION.tar.gz .
tar -xzf ./scipy-$SCIPY_VERSION.tar.gz &> archive.log
cd ./scipy-$SCIPY_VERSION
echo " configure"
echo "[DEFAULT]" > ./site.cfg
echo "library_dirs = $LAPACKDIR/lib64" >> ./site.cfg
echo "search_static_first = true" >> ./site.cfg
echo " build"
$INSTALLDIR/$x/bin/python ./setup.py build --fcompiler=gfortran &> build.log
echo " install"
$INSTALLDIR/$x/bin/python ./setup.py install &> install.log
echo " done"
done
### MatPlotLib
for x in static dynamic
do
echo "Install MatPlotLib ($x)"
cd $WORKDIR/$x
echo " extract archive"
cp $ARCHIVEDIR/matplotlib-$MATPLOTLIB_VERSION.tar.gz .
tar -xzf ./matplotlib-$MATPLOTLIB_VERSION.tar.gz &> archive.log
cd ./matplotlib-$MATPLOTLIB_VERSION
echo " build"
$INSTALLDIR/$x/bin/python ./setup.py build &> build.log
echo " install"
$INSTALLDIR/$x/bin/python ./setup.py install &> install.log
echo " done"
done
EDIT: я определил возможную причину проблемы. Если я уберу строку export LD_RUN_PATH=$INSTALLDIR/$x/lib
при установке динамического Python, мой встроенный код заработает. Я напечатал sys.path
через встроенный код, и это указывает на правильную установку. НО... таким образом я не могу использовать установку напрямую: она загружает неправильную версию, найденную в системе (когда я печатаю sys.path
, я вижу, что она указывает на /usr/...). Кроме того, я не хочу устанавливать переменные среды для запуска Python, потому что я использую несколько версий Python на одном компьютере.
EDIT: Сохраняя сценарий установки Python по умолчанию, я решаю проблему, добавляя -rdynamic в параметры при компиляции примера C++. Но я не очень понимаю, что это за вариант, и какую катастрофу он может вызвать...
make install
. Кроме того, не могли бы вы поделиться командой configure для обеих скомпилированных версий (и если были установлены какие-либо конкретные переменные env: например, CFLAGS? или любой другой пользовательский шаг). Воспроизводится ли проблема при запускеPYTHONHOME=/home/caduchon/softs/python/2.7.9/64/gcc/4.8.5/dynamic /home/caduchon/softs/python/2.7.9/64/gcc/4.8.5/static/bin/python -c "print \"abcd\""
? - person CristiFati   schedule 16.08.2017