使用 pyinstaller 规范文件制作 python pypylon 项目的 exe 文件
Make exe file of python pypylon project using pyinstaller spec file
在我的 python 项目中,我使用了 Basler GigE Vision 以太网相机,因为 pylon 不支持 python 然后我使用 pypylon.pylon wrapper to open it in python. This is my class to open the camera, but after making executable file I get errors when opening it. I used spec file to work with pyinstaller. 我得到以下错误:
import pypylon.pylon as py
import numpy as np
class PylonVideoReader:
def __init__(self, deviceName=None):
self.deviceName = deviceName
tlfactory = py.TlFactory.GetInstance()
if not self.deviceName is None:
deviceInfoList = tlfactory.EnumerateDevices()
deviceIndex = None
for i in range(len(deviceInfoList)):
if self.deviceName == deviceInfoList[i].GetUserDefinedName():
deviceIndex = i
break
if deviceIndex is None:
print("Device: {} not found please ensure that it is "
"connected".format(self.deviceName))
exit()
else:
# Create new camera
self.camera = py.InstantCamera(tlfactory.CreateDevice(
deviceInfoList[deviceIndex]))
else:
# Create new camera
self.camera = py.InstantCamera(tlfactory.CreateFirstDevice())
# Open camera
self.camera.Open()
# Set max number of frame buffers
self.camera.MaxNumBuffer = 50
# Initialize the image format converter
self.formatConverter = py.ImageFormatConverter()
# Set output pixel format to BGR8 for opencv
self.formatConverter.OutputPixelFormat = py.PixelType_BGR8packed
# Start grabbing process
self.camera.StartGrabbing(py.GrabStrategy_LatestImageOnly)
# Grab a first image to get its size
grabResult = self.camera.RetrieveResult(10000)
# Stop grabbing process
# self.camera.StopGrabbing()
# Get dimensions of image
self.frameWidth = grabResult.GetWidth()
self.frameHeight = grabResult.GetHeight()
def get(self, code):
if code == 3:
return self.frameWidth
elif code == 4:
return self.frameHeight
else:
print("{} is not a known property code".format(code))
def read(self):
# try:
# Start grabing process
# self.camera.StartGrabbing(py.GrabStrategy_LatestImageOnly)
# Grab an image
grabResult = self.camera.RetrieveResult(10000)
# Stop grabing process
# self.camera.StopGrabbing()
# Get dimensions of image
self.frameWidth = grabResult.GetWidth()
self.frameHeight = grabResult.GetHeight()
if grabResult.GrabSucceeded():
# Convert Grab result from YUV422 to BGR8
pylonImage = self.formatConverter.Convert(grabResult)
# Convert pylon image to opencv image
# image = np.frombuffer(bytearray(pylonImage.GetBuffer()), np.uint8)
image = np.asarray(bytearray(pylonImage.GetBuffer()), np.uint8)
image = image.reshape(self.frameHeight, self.frameWidth, 3)
return (True, image)
# except :
return (False, None)
def release(self):
self.camera.StopGrabbing()
self.camera.Close()
主要代码:
if __name__ == "__main__":
cap = PylonVideoReader("Admin1")
cv2.namedWindow("Test1", cv2.WINDOW_NORMAL)
while True:
ret, image = cap.read()
if ret:
cv2.imshow("Test1", image)
if cv2.waitKey(1) % 256 == ord('q'):
break
Traceback (most recent call last): File
"site-packages\pypylon\pylon.py", line 42, in swig_import_helper
File "importlib__init__.py", line 126, in import_module File
"", line 994, in _gcd_import File
"", line 971, in _find_and_load File
"", line 953, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'pypylon._pylon'
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "MainGuiLogic.py", line 18,
in File
"c:\programdata\anaconda3\lib\site-packages\PyInstaller\loader\pyimod03_importers.py",
line 631, in exec_module
exec(bytecode, module.dict) File "PylonVideoReader.py", line 1, in File
"c:\programdata\anaconda3\lib\site-packages\PyInstaller\loader\pyimod03_importers.py",
line 631, in exec_module
exec(bytecode, module.dict) File "site-packages\pypylon\pylon.py", line 45, in File
"site-packages\pypylon\pylon.py", line 44, in swig_import_helper
File "importlib__init__.py", line 126, in import_module File
"c:\programdata\anaconda3\lib\site-packages\PyInstaller\loader\pyimod03_importers.py",
line 714, in load_module
module = loader.load_module(fullname) ModuleNotFoundError: No module named 'pypylon._genicam' [4300] Failed to execute script
MainGuiLogic [4300] LOADER: OK. [4300] LOADER: Cleaning up Python
interpreter.
我通过执行以下操作解决了这个问题,有些步骤可能不是必需的,但到目前为止,这对我的情况有效。我发现 this github issue 很有帮助,让我走上了正轨。
首先,我的脚本中导入过多:
import pypylon
import pathlib
from pypylon import pylon
from pypylon import genicam
from pypylon import _genicam
from pypylon import _pylon
我反对您在示例中导入 pypylon 的方式,将包简单地称为“py”会使其他开发人员感到困惑。
接下来,我修改了规范文件的 binaries
、pathex
和 hiddenimports
。我将所有 pylon dll 和 pyd 文件添加到 binaries
,将 pypylon 目录附加到 pathex
,并将所有可能性添加到 hiddenimports
:
import pypylon
pypylon_dir = pathlib.Path(pypylon.__file__).parent
pypylon_dlls = [(str(dll), '.') for dll in pypylon_dir.glob('*.dll')]
pypylon_pyds = [(str(dll), '.') for dll in pypylon_dir.glob('*.pyd')]
_binaries = list()
_binaries.extend(pypylon_dlls)
_binaries.extend(pypylon_pyds)
_pathex = list()
_pathex.append(str(pypylon_dir))
_hiddenimports = list()
_hiddenimports.extend(['pypylon', 'pypylon.pylon', 'pypylon.genicam', 'pypylon._pylon', 'pypylon._genicam'])
a = Analysis(...
pathex=_pathex,
binaries=_binaries,
...
hiddenimports=_hiddenimports,
我不确定所有这些都是绝对必要的,但它适用于 Python 3.4、PyInstaller 3.3 和 pypylon 1.3.1。
祝你好运!
使用pyinstaller (How to make executable file with pyinstaller)制作可执行文件后,您应该从项目中使用的虚拟环境中找到pypylon文件夹,然后复制exe文件旁边的pypylon文件夹。
在我的 python 项目中,我使用了 Basler GigE Vision 以太网相机,因为 pylon 不支持 python 然后我使用 pypylon.pylon wrapper to open it in python. This is my class to open the camera, but after making executable file I get errors when opening it. I used spec file to work with pyinstaller. 我得到以下错误:
import pypylon.pylon as py
import numpy as np
class PylonVideoReader:
def __init__(self, deviceName=None):
self.deviceName = deviceName
tlfactory = py.TlFactory.GetInstance()
if not self.deviceName is None:
deviceInfoList = tlfactory.EnumerateDevices()
deviceIndex = None
for i in range(len(deviceInfoList)):
if self.deviceName == deviceInfoList[i].GetUserDefinedName():
deviceIndex = i
break
if deviceIndex is None:
print("Device: {} not found please ensure that it is "
"connected".format(self.deviceName))
exit()
else:
# Create new camera
self.camera = py.InstantCamera(tlfactory.CreateDevice(
deviceInfoList[deviceIndex]))
else:
# Create new camera
self.camera = py.InstantCamera(tlfactory.CreateFirstDevice())
# Open camera
self.camera.Open()
# Set max number of frame buffers
self.camera.MaxNumBuffer = 50
# Initialize the image format converter
self.formatConverter = py.ImageFormatConverter()
# Set output pixel format to BGR8 for opencv
self.formatConverter.OutputPixelFormat = py.PixelType_BGR8packed
# Start grabbing process
self.camera.StartGrabbing(py.GrabStrategy_LatestImageOnly)
# Grab a first image to get its size
grabResult = self.camera.RetrieveResult(10000)
# Stop grabbing process
# self.camera.StopGrabbing()
# Get dimensions of image
self.frameWidth = grabResult.GetWidth()
self.frameHeight = grabResult.GetHeight()
def get(self, code):
if code == 3:
return self.frameWidth
elif code == 4:
return self.frameHeight
else:
print("{} is not a known property code".format(code))
def read(self):
# try:
# Start grabing process
# self.camera.StartGrabbing(py.GrabStrategy_LatestImageOnly)
# Grab an image
grabResult = self.camera.RetrieveResult(10000)
# Stop grabing process
# self.camera.StopGrabbing()
# Get dimensions of image
self.frameWidth = grabResult.GetWidth()
self.frameHeight = grabResult.GetHeight()
if grabResult.GrabSucceeded():
# Convert Grab result from YUV422 to BGR8
pylonImage = self.formatConverter.Convert(grabResult)
# Convert pylon image to opencv image
# image = np.frombuffer(bytearray(pylonImage.GetBuffer()), np.uint8)
image = np.asarray(bytearray(pylonImage.GetBuffer()), np.uint8)
image = image.reshape(self.frameHeight, self.frameWidth, 3)
return (True, image)
# except :
return (False, None)
def release(self):
self.camera.StopGrabbing()
self.camera.Close()
主要代码:
if __name__ == "__main__":
cap = PylonVideoReader("Admin1")
cv2.namedWindow("Test1", cv2.WINDOW_NORMAL)
while True:
ret, image = cap.read()
if ret:
cv2.imshow("Test1", image)
if cv2.waitKey(1) % 256 == ord('q'):
break
Traceback (most recent call last): File "site-packages\pypylon\pylon.py", line 42, in swig_import_helper
File "importlib__init__.py", line 126, in import_module File "", line 994, in _gcd_import File "", line 971, in _find_and_load File "", line 953, in _find_and_load_unlocked ModuleNotFoundError: No module named 'pypylon._pylon'During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "MainGuiLogic.py", line 18, in File "c:\programdata\anaconda3\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 631, in exec_module exec(bytecode, module.dict) File "PylonVideoReader.py", line 1, in File "c:\programdata\anaconda3\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 631, in exec_module exec(bytecode, module.dict) File "site-packages\pypylon\pylon.py", line 45, in File "site-packages\pypylon\pylon.py", line 44, in swig_import_helper
File "importlib__init__.py", line 126, in import_module File "c:\programdata\anaconda3\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 714, in load_module module = loader.load_module(fullname) ModuleNotFoundError: No module named 'pypylon._genicam' [4300] Failed to execute script MainGuiLogic [4300] LOADER: OK. [4300] LOADER: Cleaning up Python interpreter.
我通过执行以下操作解决了这个问题,有些步骤可能不是必需的,但到目前为止,这对我的情况有效。我发现 this github issue 很有帮助,让我走上了正轨。
首先,我的脚本中导入过多:
import pypylon
import pathlib
from pypylon import pylon
from pypylon import genicam
from pypylon import _genicam
from pypylon import _pylon
我反对您在示例中导入 pypylon 的方式,将包简单地称为“py”会使其他开发人员感到困惑。
接下来,我修改了规范文件的 binaries
、pathex
和 hiddenimports
。我将所有 pylon dll 和 pyd 文件添加到 binaries
,将 pypylon 目录附加到 pathex
,并将所有可能性添加到 hiddenimports
:
import pypylon
pypylon_dir = pathlib.Path(pypylon.__file__).parent
pypylon_dlls = [(str(dll), '.') for dll in pypylon_dir.glob('*.dll')]
pypylon_pyds = [(str(dll), '.') for dll in pypylon_dir.glob('*.pyd')]
_binaries = list()
_binaries.extend(pypylon_dlls)
_binaries.extend(pypylon_pyds)
_pathex = list()
_pathex.append(str(pypylon_dir))
_hiddenimports = list()
_hiddenimports.extend(['pypylon', 'pypylon.pylon', 'pypylon.genicam', 'pypylon._pylon', 'pypylon._genicam'])
a = Analysis(...
pathex=_pathex,
binaries=_binaries,
...
hiddenimports=_hiddenimports,
我不确定所有这些都是绝对必要的,但它适用于 Python 3.4、PyInstaller 3.3 和 pypylon 1.3.1。
祝你好运!
使用pyinstaller (How to make executable file with pyinstaller)制作可执行文件后,您应该从项目中使用的虚拟环境中找到pypylon文件夹,然后复制exe文件旁边的pypylon文件夹。