PyQt5/PyQt

我在c++代码里调用python的脚本.使用接口PyImport_Import import的是一个存粹的python的脚本可以成功,但是如果import的是pyqt的脚本,就会失败

maoliangwu opened this issue · 5 comments

Environment : / 环境

  • OS: Win 10
  • Python 3.7.9 x86
  • PyQt5 PyQt5_Qt5-5.15.2

我有两个脚本一个是test.py
def fun():
print("Something that provides mirth or amusement")
另一个是hellopyqt.py
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot

def fun():
app = QApplication(sys.argv)
widget = QWidget()

textLabel = QLabel(widget)
textLabel.setText("Hello World!")
textLabel.move(110,85)

widget.setGeometry(50,50,320,200)
widget.setWindowTitle("PyQt5 Example")
widget.show()
sys.exit(app.exec_())

#if name == 'main':

fun()

我在qtcreator中创建了一个c++的qt工程
主要是用来加载py模块,调用Py脚本中的方法。
当我import “test.py”的时候PyImport_Import可以返回正确的值,但是如果import的是pyqt的那个脚本“hellopyqt.py”时,接口返回的时null。
我的两个脚本直接双击运行都时没有问题的。
我在电脑上已经安装了pyqt5 C:\Users**\AppData\Local\Programs\Python\Python37-32\Lib\site-packages
并且我已经添加了环境变量
PYTHONPATH = C:\Users*
\AppData\Local\Programs\Python\Python37-32\Lib\site-packages

project url:https://github.com/maoliangwu/c-call-pyqt

你可能还需要设置qt相关的路径

from distutils.sysconfig import get_python_lib
libpath = get_python_lib()
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = os.path.join(
    libpath, 'PyQt5', 'Qt', 'plugins', 'platforms')
os.environ['QML_IMPORT_PATH'] = os.path.join(libpath, 'Qt', 'qml')
os.environ['QML2_IMPORT_PATH'] = os.environ['QML_IMPORT_PATH']

if os.name == 'nt':
    os.environ['PATH'] = os.path.join(
        libpath, 'PyQt5', 'Qt', 'bin') + os.pathsep + os.environ['PATH']
os.environ['PATH'] = os.path.dirname(
    os.path.abspath(sys.argv[0])) + os.pathsep + os.environ['PATH']

print(os.environ['PATH'])

另外晚点我发下之前PyQtClient里面编译的启动exe里面的源码

或者还有个工具交pybind11 很方便c++调用py(可能也需要设置Qt相关变量)

你可能还需要设置qt相关的路径

from distutils.sysconfig import get_python_lib
libpath = get_python_lib()
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = os.path.join(
    libpath, 'PyQt5', 'Qt', 'plugins', 'platforms')
os.environ['QML_IMPORT_PATH'] = os.path.join(libpath, 'Qt', 'qml')
os.environ['QML2_IMPORT_PATH'] = os.environ['QML_IMPORT_PATH']

if os.name == 'nt':
    os.environ['PATH'] = os.path.join(
        libpath, 'PyQt5', 'Qt', 'bin') + os.pathsep + os.environ['PATH']
os.environ['PATH'] = os.path.dirname(
    os.path.abspath(sys.argv[0])) + os.pathsep + os.environ['PATH']

print(os.environ['PATH'])

另外晚点我发下之前PyQtClient里面编译的启动exe里面的源码

或者还有个工具交pybind11 很方便c++调用py(可能也需要设置Qt相关变量)

在脚本里加了你说的这段代码,但是没有用,奇怪,这个脚本单独运行是没有问题的。但是用c的接口调用就不行。感觉确实是可能哪里环境没有配置好,而且发现跟pyqt好像也没关系,如果我import了site-package里面的一些其他的包,也可能会出现这个问题

那就是python环境变量的问题
PYTHONPATH
PYTHONHOME
等等

比如参考linux下的设置

export PYTHONHOME=当前路径
export PYTHONPATH=当前路径/python3.6/:当前路径/python3.6/dlls/:当前路径/python3.6/site-packages/:当前路径/python3.6/site-packages/

另外也可以通过在代码里import sys添加

最简单的可以用 pybind11

比如:https://blog.csdn.net/thisisfangsheng/article/details/75610558

你可能还需要设置qt相关的路径

from distutils.sysconfig import get_python_lib
libpath = get_python_lib()
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = os.path.join(
    libpath, 'PyQt5', 'Qt', 'plugins', 'platforms')
os.environ['QML_IMPORT_PATH'] = os.path.join(libpath, 'Qt', 'qml')
os.environ['QML2_IMPORT_PATH'] = os.environ['QML_IMPORT_PATH']

if os.name == 'nt':
    os.environ['PATH'] = os.path.join(
        libpath, 'PyQt5', 'Qt', 'bin') + os.pathsep + os.environ['PATH']
os.environ['PATH'] = os.path.dirname(
    os.path.abspath(sys.argv[0])) + os.pathsep + os.environ['PATH']

print(os.environ['PATH'])

另外晚点我发下之前PyQtClient里面编译的启动exe里面的源码

或者还有个工具交pybind11 很方便c++调用py(可能也需要设置Qt相关变量)

好的,我周末试试pybind11。关于前面的哪个问题,我发现是pyqt的py文件后缀是pyi,当我使用c接口PyImport_Import传入hellopyqt.py,提示的错误是找不到PyQt5.QtWidgets,我把site-packages里面的PyQt5里面的QtWidgets.pyi改名位QtWidgets.py。去掉了最后一个i以后它就不再报找不到模块的这个问题了。这个是什么缘故,你知道吗

在初始化解释器前需要设置一些三方库路径,比如:

	Py_SetPythonHome((wchar_t*)(L"./"));
	Py_SetPath(L"DLLs;python35.zip;Lib;Lib/site-packages");   //设置库
	Py_Initialize();

可以查一下这方面的资料