代码之家  ›  专栏  ›  技术社区  ›  wesley silva

Pyinstaller在windows上生成失败,原因是argparse(警告:stderr:SystemExit:2)

  •  0
  • wesley silva  · 技术社区  · 2 年前

    我有这个项目 qrTransfer 关于使用QrCode在PC和移动设备之间发送文件。我想用当前的dev为Windows创建一个dev构建 code 但我在运行pyinstaller时收到了下面的错误。然而,在Linux上,我可以毫无问题地进行构建。最后,Windows的上一次构建是在大约一年半前完成的,我忘记添加Pyinstaller版本使用的文档,但我很确定这是当时最新的。

    错误:

     usage: _child.py [-h] [-p path_list [path_list ...]] [-ptm] [-mtp] [--remote] [--debug]
     _child.py: error: unrecognized arguments: 732 824
    67802 WARNING: stderr: Traceback (most recent call last):
     Traceback (most recent call last):
    67802 WARNING: stderr:   File "<frozen runpy>", line 198, in _run_module_as_main
       File "<frozen runpy>", line 198, in _run_module_as_main
    67802 WARNING: stderr:   File "<frozen runpy>", line 88, in _run_code
       File "<frozen runpy>", line 88, in _run_code
    67802 WARNING: stderr:   File "C:\Users\win-builder\Envs\qrt\Scripts\pyinstaller.exe\__main__.py", line 7, in <module>
       File "C:\Users\win-builder\Envs\qrt\Scripts\pyinstaller.exe\__main__.py", line 7, in <module>
    67802 WARNING: stderr:   File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\__main__.py", line 205, in _console_script_run
       File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\__main__.py", line 205, in _console_script_run
    67802 WARNING: stderr:     run()
         run()
    67802 WARNING: stderr:   File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\__main__.py", line 189, in run
       File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\__main__.py", line 189, in run
    67802 WARNING: stderr:     run_build(pyi_config, spec_file, **vars(args))
         run_build(pyi_config, spec_file, **vars(args))
    67802 WARNING: stderr:   File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\__main__.py", line 61, in run_build
       File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\__main__.py", line 61, in run_build
    67802 WARNING: stderr:     PyInstaller.building.build_main.main(pyi_config, spec_file, **kwargs)
         PyInstaller.building.build_main.main(pyi_config, spec_file, **kwargs)
    67802 WARNING: stderr:   File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\building\build_main.py", line 1033, in main
       File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\building\build_main.py", line 1033, in main
    67802 WARNING: stderr:     build(specfile, distpath, workpath, clean_build)
         build(specfile, distpath, workpath, clean_build)
    67818 WARNING: stderr:   File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\building\build_main.py", line 973, in build
       File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\building\build_main.py", line 973, in build
    67818 WARNING: stderr:     exec(code, spec_namespace)
         exec(code, spec_namespace)
    67818 WARNING: stderr:   File "C:\Users\win-builder\Documents\qrTransfer\qrTransfer.exe.spec", line 4, in <module>
       File "C:\Users\win-builder\Documents\qrTransfer\qrTransfer.exe.spec", line 4, in <module>
    67818 WARNING: stderr:     a = Analysis(
         a = Analysis(
    67818 WARNING: stderr:         ^^^^^^^^^
             ^^^^^^^^^
    67818 WARNING: stderr:   File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\building\build_main.py", line 466, in __init__
       File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\building\build_main.py", line 466, in __init__
    67818 WARNING: stderr:     self.__postinit__()
         self.__postinit__()
    67818 WARNING: stderr:   File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\building\datastruct.py", line 184, in __postinit__
       File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\building\datastruct.py", line 184, in __postinit__
    67818 WARNING: stderr:     self.assemble()
         self.assemble()
    67818 WARNING: stderr:   File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\building\build_main.py", line 791, in assemble
       File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\building\build_main.py", line 791, in assemble
    67818 WARNING: stderr:     self.binaries.extend(find_binary_dependencies(self.binaries, collected_packages))
         self.binaries.extend(find_binary_dependencies(self.binaries, collected_packages))
    67818 WARNING: stderr:                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    67818 WARNING: stderr:   File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\building\build_main.py", line 216, in find_binary_dependencies
       File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\building\build_main.py", line 216, in find_binary_dependencies
    67818 WARNING: stderr:     child.call(import_library, package)
         child.call(import_library, package)
    67818 WARNING: stderr:   File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\isolated\_parent.py", line 319, in call
       File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\isolated\_parent.py", line 319, in call
    67818 WARNING: stderr:     raise RuntimeError(f"Child process call to {function.__name__}() failed with:\n" + output)
         raise RuntimeError(f"Child process call to {function.__name__}() failed with:\n" + output)
    67818 WARNING: stderr: RuntimeError: Child process call to import_library() failed with:
     RuntimeError: Child process call to import_library() failed with:
    67818 WARNING: stderr:   File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\isolated\_child.py", line 63, in run_next_command
       File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\isolated\_child.py", line 63, in run_next_command
    67818 WARNING: stderr:     output = function(*args, **kwargs)
         output = function(*args, **kwargs)
    67818 WARNING: stderr:              ^^^^^^^^^^^^^^^^^^^^^^^^^
                  ^^^^^^^^^^^^^^^^^^^^^^^^^
    67818 WARNING: stderr:   File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\building\build_main.py", line 194, in import_library
       File "C:\Users\win-builder\Envs\qrt\Lib\site-packages\PyInstaller\building\build_main.py", line 194, in import_library
    67818 WARNING: stderr:     __import__(package)
         __import__(package)
    67818 WARNING: stderr:   File "C:\Users\win-builder\Documents\qrTransfer\src\display\__init__.py", line 1, in <module>
       File "C:\Users\win-builder\Documents\qrTransfer\src\display\__init__.py", line 1, in <module>
    67818 WARNING: stderr:     from .qrWindow import qr_window
         from .qrWindow import qr_window
    67818 WARNING: stderr:   File "C:\Users\win-builder\Documents\qrTransfer\src\display\qrWindow.py", line 9, in <module>
       File "C:\Users\win-builder\Documents\qrTransfer\src\display\qrWindow.py", line 9, in <module>
    67818 WARNING: stderr:     from utils import ROOT_DIR
         from utils import ROOT_DIR
    67818 WARNING: stderr:   File "C:\Users\win-builder\Documents\qrTransfer\src\utils\__init__.py", line 2, in <module>
       File "C:\Users\win-builder\Documents\qrTransfer\src\utils\__init__.py", line 2, in <module>
    67818 WARNING: stderr:     from .logger import logger
         from .logger import logger
    67818 WARNING: stderr:   File "C:\Users\win-builder\Documents\qrTransfer\src\utils\logger.py", line 3, in <module>
       File "C:\Users\win-builder\Documents\qrTransfer\src\utils\logger.py", line 3, in <module>
    67818 WARNING: stderr:     from .cli import args
         from .cli import args
    67818 WARNING: stderr:   File "C:\Users\win-builder\Documents\qrTransfer\src\utils\cli.py", line 79, in <module>
       File "C:\Users\win-builder\Documents\qrTransfer\src\utils\cli.py", line 79, in <module>
    67818 WARNING: stderr:     args = setup_arg_parser()
         args = setup_arg_parser()
    67818 WARNING: stderr:           ^^^^^^^^^^^^^^^^^^
               ^^^^^^^^^^^^^^^^^^
    67818 WARNING: stderr:   File "C:\Users\win-builder\Documents\qrTransfer\src\utils\cli.py", line 45, in setup_arg_parser
       File "C:\Users\win-builder\Documents\qrTransfer\src\utils\cli.py", line 45, in setup_arg_parser
    67818 WARNING: stderr:     return parser.parse_args()
         return parser.parse_args()
    67818 WARNING: stderr:            ^^^^^^^^^^^^^^^^^^^
                ^^^^^^^^^^^^^^^^^^^
    67818 WARNING: stderr:   File "C:\Users\win-builder\AppData\Local\Programs\Python\Python311\Lib\argparse.py", line 1872, in parse_args
       File "C:\Users\win-builder\AppData\Local\Programs\Python\Python311\Lib\argparse.py", line 1872, in parse_args
    67818 WARNING: stderr:     self.error(msg % ' '.join(argv))
         self.error(msg % ' '.join(argv))
    67818 WARNING: stderr:   File "C:\Users\win-builder\AppData\Local\Programs\Python\Python311\Lib\argparse.py", line 2630, in error
       File "C:\Users\win-builder\AppData\Local\Programs\Python\Python311\Lib\argparse.py", line 2630, in error
    67818 WARNING: stderr:     self.exit(2, _('%(prog)s: error: %(message)s\n') % args)
         self.exit(2, _('%(prog)s: error: %(message)s\n') % args)
    67818 WARNING: stderr:   File "C:\Users\win-builder\AppData\Local\Programs\Python\Python311\Lib\argparse.py", line 2617, in exit
       File "C:\Users\win-builder\AppData\Local\Programs\Python\Python311\Lib\argparse.py", line 2617, in exit
    67818 WARNING: stderr:     _sys.exit(status)
         _sys.exit(status)
    67818 WARNING: stderr: SystemExit: 2
     SystemExit: 2
    

    通常我用这个构建 script (我知道最后有一些常规的'/'——添加数据,但修复它不会改变任何东西),但直接运行Pyinstaller也会出现同样的错误

    @echo off
    
    setlocal 
    cd /d %~dp0
    
    set root=..\..
    set out=..\%root%\build
    
    if not exist %out% (
        mkdir %out%
    )
    
    if exist %out%\dist (
        rmdir /Q /S %out%\dist
    )
    
    
    pyinstaller^
     --add-data "%root%\display\kvFiles;display\kvFiles"^
     --add-data "%root%\resources;resources"^
     --add-data "%root%/server/templates;server/templates"^
     --icon "%root%\resources\icon.ico"^
     --onefile --distpath "%out%\dist"^
     --workpath "%out%\build" -n qrTransfer.exe "%root%\main.py"
    

    这是我设置的位置 argparse

    import argparse, sys
    from pathlib import Path
    
    __all__ = ['args']
    
    
    def setup_arg_parser():
        parser = argparse.ArgumentParser(
            description='Provides a QRcode to download or upload a file. \
            Commands described here take server\'s point of view. Have in \
            mind that '
        )
    
        parser.add_argument('-p',
                            metavar='path_list',
                            dest='path_list',
                            nargs='+',
                            help='- Paths to the files which download code \
                            will be generated. (Only -ptm mode)')
    
        parser.add_argument('-ptm',
                            '--pc-to-mobile',
                            action='store_false',
                            help='- [DEFAULT] Starts the program to upload \
                            a file to other device')
    
        parser.add_argument('-mtp',
                            '--mobile-to-pc',
                            action='store_true',
                            help='- Starts the program to download a file \
                            from another device'
        )
    
        parser.add_argument('--remote',
                            action='store_true',
                            dest='shall_remote_upload',
                            help='- Enables transfer through the remote \
                            service file.io'
        )
    
        parser.add_argument('--debug',
                            action='store_true',
                            help='- Enables debug mode.'
        )
        return parser.parse_args()
    
    
    def validate_args(args):
        if  args.mobile_to_pc:
            args.pc_to_mobile = False
        else:
            validate_path_list(args)
    
    
    def validate_path_list(args):
        if not args.path_list:
            print('Path (-p) not provided. Check help (-h) for more info.')
            sys.exit(1)
    
        paths = args.path_list
        for i, path_str in enumerate(paths):
            paths[i] = Path(path_str.strip()).absolute()
            validate_path(paths[i])
    
    
    def validate_path(p : Path):
        if (p.is_file() or p.is_dir()): return True
        print(f'The path {p} does not exist.')
        sys.exit(1)
    
    
    class MockArgs:
        mobile_to_pc = True
        pc_to_mobile = False
        debug = False
    
    
    if not 'pytest' in sys.modules:
        args = setup_arg_parser() 
        validate_args(args)
    else:
        args = MockArgs()
    
    
    if __name__ == '__main__':
        print(args.path_list)
    

    值得一提的是,我尝试了auto-py-exe,结果是一样的。此外,我看到了一个涉及Pyinstaller和argparse的问题的答案,它说我应该更改 parser.parse_args() parser.parse_args(sys.argv[1:]) 但是结果仍然是一样的。

    0 回复  |  直到 2 年前
        1
  •  0
  •   wesley silva    2 年前

    我找到了 workaround 。似乎发生的情况是,我的argparse定义与Pyinstaller中的一些argparse的定义混淆了。然后,我添加了一个检查,以确保只有当执行的脚本被称为“main.py”时,才会解析参数

    name_of_main_file = Path(__main__.__file__).name
    if not 'pytest' in sys.modules and name_of_main_file == 'main.py':
        args = setup_arg_parser() 
        validate_args(args)
    else:
        args = MockArgs()