python Pyinstaller在Windows上构建失败,因为argparse(args:stderr:SystemExit:(二)

omvjsjqw  于 2023-10-15  发布在  Python
关注(0)|答案(1)|浏览(104)

我有一个关于使用QrCode在PC和移动的设备之间发送文件的项目qrTransfer。我想用当前的dev code为Windows创建一个dev build,但在运行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构建(我知道最后一个--add-data中有常规的'/',但修复它不会改变任何东西),但直接运行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-to-exe,结果是一样的。另外,我看到了一个涉及Pyinstaller和argparse的问题的答案,说我应该将parser.parse_args()更改为parser.parse_args(sys.argv[1:]),但结果仍然是一样的。

yhuiod9q

yhuiod9q1#

我找到了workaround。似乎发生的是我的argparse定义与Pyinstaller的一些argparse定义混淆了。然后,我添加了一个检查,以确保只有当执行的脚本被称为“www.example.com“时,args才会被解析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()

相关问题