使用 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”会使其他开发人员感到困惑。

接下来,我修改了规范文件的 binariespathexhiddenimports。我将所有 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文件夹。