代码之家  ›  专栏  ›  技术社区  ›  tinman

pyinstaller和应用程序中的版本号

  •  1
  • tinman  · 技术社区  · 3 年前

    我有一个应用程序,我想在其中包含一些版本信息,并且只在一个位置定义它。我在Windows上运行,所以我想设置可执行文件的版本资源,并使用pyinstaller构建可执行文件,但也希望能够访问应用程序本身的版本信息。

    到目前为止,我已经遵循了在C中可以实现的相同路径——创建一个具有值的头,将该头包含在应用程序代码和资源脚本中,然后能够使用预处理器符号中的单个定义。我想我可以在python中做一些类似的事情。

    到目前为止,我已经创建了一个版本号为的version_ifo.py文件:

    MYAPPLICATION_VERSION_MAJOR = 4
    MYAPPLICATION_VERSION_MINOR = 2
    MYAPPLICATION_VERSION_PATCH = 0
    MYAPPLICATION_VERSION_BUILD = 0
    

    然后,我可以在我的应用程序源代码中包含这一点,没有问题(为了简洁起见,请减少,因为这不是问题所在):

    import version_info
    print(f'{version_info.MYAPPLICATION_VERSION_MAJOR}.{version_info.MYAPPLICATION_VERSION_MINOR}.{version_info.MYAPPLICATION_VERSION_PATCH}')
    

    我可以使用具有硬编码值的“file_version_info”类型文件,并且包含Windows版本资源也可以。

    # UTF-8
    #
    # For more details about fixed file info 'ffi' see:
    # http://msdn.microsoft.com/en-us/library/ms646997.aspx
    
    VSVersionInfo(
      ffi=FixedFileInfo(
        # filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
        # Set not needed items to zero 0.
        filevers=(1, 2, 0, 0),
        prodvers=(1, 2, 0, 0),
        # Contains a bitmask that specifies the valid bits 'flags'r
        mask=0x3f,
        # Contains a bitmask that specifies the Boolean attributes of the file.
        flags=0x0,
        # The operating system for which this file was designed.
        # 0x4 - NT and there is no need to change it.
        OS=0x4,
        # The general type of file.
        # 0x1 - the file is an application.
        fileType=0x1,
        # The function of the file.
        # 0x0 - the function is not defined for this fileType
        subtype=0x0,
        # Creation date and time stamp.
        date=(0, 0)
        ),
      kids=[
        StringFileInfo(
          [
          StringTable(
            '080904b0', # 0809 = en-GB, 04b0 = Unicode
            [StringStruct('CompanyName', 'My company'),
            StringStruct('FileDescription', 'Application file description.'),
            StringStruct('FileVersion', '1.2.0.0'),
            StringStruct('InternalName', 'MyApplication.exe'),
            StringStruct('LegalCopyright', 'Copyright (C) 2021-2023 My Company, All rights reserved.'),
            StringStruct('OriginalFilename', 'MyApplication.exe'),
            StringStruct('ProductName', 'My product'),
            StringStruct('ProductVersion', '1.2.0.0')])
          ]), 
        VarFileInfo([VarStruct('Translation', [0x0809, 1200])])
      ]
    )
    

    我的应用程序有一个pyinstaller规范文件,该文件引入了一个版本信息定义来设置Windows版本详细信息:

    # -*- mode: python ; coding: utf-8 -*-
    
    
    block_cipher = None
    
    
    a = Analysis(
        ['MyApplication/main.py'],
        pathex=['MyApplication'],
        binaries=[],
        datas=[],
        hiddenimports=[],
        hookspath=[],
        hooksconfig={},
        runtime_hooks=[],
        excludes=['sqlite', 'tbb'],
        win_no_prefer_redirects=False,
        win_private_assemblies=False,
        cipher=block_cipher,
        noarchive=False,
    )
    pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
    splash = Splash(
        'splash.png',
        binaries=a.binaries,
        datas=a.datas,
        text_pos=None,
        text_size=12,
        minify_script=True,
        always_on_top=False,
    )
    
    exe = EXE(
        pyz,
        a.scripts,
        splash,
        [],
        exclude_binaries=True,
        name='MyApplication',
        debug=False,
        bootloader_ignore_signals=False,
        strip=False,
        upx=True,
        console=False,
        disable_windowed_traceback=False,
        argv_emulation=False,
        target_arch=None,
        codesign_identity=None,
        entitlements_file=None,
        version='MyApplication/file_version_info.py',
    )
    coll = COLLECT(
        exe,
        a.binaries,
        a.zipfiles,
        a.datas,
        splash.binaries,
        strip=False,
        upx=True,
        upx_exclude=[],
        name='MyApplication',
    )
    

    我遇到的问题是,当我尝试使用 file_version_info pyinstaller规范文件的文件。我不知道如何包含和使用这些定义。我尝试过import的变体,发现pyinstaller使用 eval() 关于版本信息,所以我得到的最接近的信息是:

    # UTF-8
    #
    # For more details about fixed file info 'ffi' see:
    # http://msdn.microsoft.com/en-us/library/ms646997.aspx
    
    exec("import version_info")
    
    VSVersionInfo(
      ffi=FixedFileInfo(
        # filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
        # Set not needed items to zero 0.
        filevers=(1, 2, 0, 0),
        prodvers=(1, 2, 0, 0),
        # Contains a bitmask that specifies the valid bits 'flags'r
        mask=0x3f,
        # Contains a bitmask that specifies the Boolean attributes of the file.
        flags=0x0,
        # The operating system for which this file was designed.
        # 0x4 - NT and there is no need to change it.
        OS=0x4,
        # The general type of file.
        # 0x1 - the file is an application.
        fileType=0x1,
        # The function of the file.
        # 0x0 - the function is not defined for this fileType
        subtype=0x0,
        # Creation date and time stamp.
        date=(0, 0)
        ),
      kids=[
        StringFileInfo(
          [
          StringTable(
            '080904b0', # 0809 = en-GB, 04b0 = Unicode
            [StringStruct('CompanyName', 'My company'),
            StringStruct('FileDescription', 'Application file description.'),
            StringStruct('FileVersion', '1.2.0.0'),
            StringStruct('InternalName', 'MyApplication.exe'),
            StringStruct('LegalCopyright', 'Copyright (C) 2021-2023 My Company, All rights reserved.'),
            StringStruct('OriginalFilename', 'MyApplication.exe'),
            StringStruct('ProductName', 'My product'),
            StringStruct('ProductVersion', '1.2.0.0')])
          ]), 
        VarFileInfo([VarStruct('Translation', [0x0809, 1200])])
      ]
    )
    

    但在这种情况下,我最终得到了错误:

      File "<string>", line 8
        VSVersionInfo(
        ^^^^^^^^^^^^^
    SyntaxError: invalid syntax
    

    这对我来说似乎很奇怪,因为我可以表演 eval('exec("import version_info.py")') 在命令行上,它是正常的。

    所以我的问题是:我如何在一个地方定义版本号,以便python代码和pyinstaller版本资源可以使用该通用定义。

    0 回复  |  直到 3 年前
        1
  •  0
  •   tinman    3 年前

    无法使用的原因 exec("import version_info") 在file_version_info文件中,并且得到SyntaxError是因为pyinstaller使用该文件的方式。它将文件的内容读取为字符串,然后调用 vs = eval(txt) 。因此,在考虑赋值时,文件的内容必须有一个有效的语法 exec() 呼叫中断。

    我最终使用的解决方案是在一个独立的python源代码中定义版本字段,我可以从代码中导入这些字段,还编写了一个简单的python源代码来生成 file_version_info 文件。当我构建可执行文件时,我使用shell脚本来运行 文件版本信息 在运行pyinstaller之前立即启动发电机。

    我本可以采用的另一种选择是在运行时从代码中读取exe中的版本信息。但是,我不想使用这种方法,因为在调试时不会出现版本信息。