“没有找到分销,并且是由应用程序要求的。”当使用pyinstaller与setuptools

发布于 2025-01-17 11:26:04 字数 5544 浏览 4 评论 0原文

我正在尝试从setuptools发行版中实现可执行文件,我有以下结构:

TEST-DIST
├── app.spec
├── my_package
│   ├── __init__.py
│   ├── __main__.py
│   ├── script1.py
│   └── script2.py
└── setup.py

setup.py:

from importlib.metadata import entry_points
import setuptools

setuptools.setup(
    name="testapp",
    version="0.0.1",
    author="Example Author",
    author_email="[email protected]",
    description="A small example package",
    url="https://github.com/pypa/sampleproject",
    project_urls={
        "Bug Tracker": "https://github.com/pypa/sampleproject/issues",
    },
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    entry_points={'console_scripts': ["mytestscript1=my_package.script1:main", "mytestscript2=my_package.script2:main"]},
    python_requires=">=3.6"
)

app.spec,使用此脚本要与setuptools一起使用,

block_cipher = None


def Entrypoint(dist, group, name, **kwargs):
    import pkg_resources

    # get toplevel packages of distribution from metadata
    def get_toplevel(dist):
        distribution = pkg_resources.get_distribution(dist)
        if distribution.has_metadata('top_level.txt'):
            return list(distribution.get_metadata('top_level.txt').split())
        else:
            return []

    kwargs.setdefault('hiddenimports', [])
    packages = []
    for distribution in kwargs['hiddenimports']:
        packages += get_toplevel(distribution)

    kwargs.setdefault('pathex', [])
    # get the entry point
    ep = pkg_resources.get_entry_info(dist, group, name)
    # insert path of the egg at the verify front of the search path
    kwargs['pathex'] = [ep.dist.location] + kwargs['pathex']
    # script name must not be a valid module name to avoid name clashes on import
    script_path = os.path.join(workpath, name + '-script.py')
    print("creating script for entry point", dist, group, name)
    with open(script_path, 'w') as fh:
        print("import", ep.module_name, file=fh)
        print("%s.%s()" % (ep.module_name, '.'.join(ep.attrs)), file=fh)
        for package in packages:
            print("import", package, file=fh)

    return Analysis(
        [script_path] + kwargs.get('scripts', []),
        **kwargs
    )

a = Entrypoint("testapp", 'console_scripts', 'mytestscript1')
pyz = PYZ(a.pure, a.zipped_data)

exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='mytestscript1')

我首先使用python3 -m构建,然后我执行Pyinstaller pyinstaller pyinstaller app.spec.spec.spec.spec.spec.spec。,导致以下错误:

27 INFO: PyInstaller: 4.10
27 INFO: Python: 3.8.10
34 INFO: Platform: Linux-5.10.60.1-microsoft-standard-WSL2-x86_64-with-glibc2.29
35 INFO: UPX is not available.
Traceback (most recent call last):
  File "/usr/local/bin/pyinstaller", line 8, in <module>
    sys.exit(run())
  File "/home/admin/.local/lib/python3.8/site-packages/PyInstaller/__main__.py", line 124, in run
    run_build(pyi_config, spec_file, **vars(args))
  File "/home/admin/.local/lib/python3.8/site-packages/PyInstaller/__main__.py", line 58, in run_build
    PyInstaller.building.build_main.main(pyi_config, spec_file, **kwargs)
  File "/home/admin/.local/lib/python3.8/site-packages/PyInstaller/building/build_main.py", line 803, in main
    build(specfile, distpath, workpath, clean_build)
  File "/home/admin/.local/lib/python3.8/site-packages/PyInstaller/building/build_main.py", line 725, in build
    exec(code, spec_namespace)
  File "app.spec", line 42, in <module>
    a = Entrypoint("testapp", 'console_scripts', 'mytestscript1', datas=[('testapp.egg-info/*','testapp.egg-info')])
  File "app.spec", line 25, in Entrypoint
    ep = pkg_resources.get_entry_info(dist, group, name)
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 500, in get_entry_info
    return get_distribution(dist).get_entry_info(group, name)
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 482, in get_distribution
    dist = get_provider(dist)
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 358, in get_provider
    return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0]
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 901, in require
    needed = self.resolve(parse_requirements(requirements))
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 787, in resolve
    raise DistributionNotFound(req, requirers)
pkg_resources.DistributionNotFound: The 'testapp' distribution was not found and is required by the application

调用异常是因为pkg_resources.get_entry_info在从Pyinstaller执行时找不到我的发行版,但是当我从任何正常脚本中运行它root可以找到没有问题的发现:

>>> import pkg_resources
>>> pkg_resources.get_entry_info("testapp", 'console_scripts', 'mytestscript1')
EntryPoint.parse('mytestscript1 = my_package.script1:main')

没有解决方案在这里

I am trying to make an executable from a setuptools distribution, I have the following structure:

TEST-DIST
├── app.spec
├── my_package
│   ├── __init__.py
│   ├── __main__.py
│   ├── script1.py
│   └── script2.py
└── setup.py

Setup.py:

from importlib.metadata import entry_points
import setuptools

setuptools.setup(
    name="testapp",
    version="0.0.1",
    author="Example Author",
    author_email="[email protected]",
    description="A small example package",
    url="https://github.com/pypa/sampleproject",
    project_urls={
        "Bug Tracker": "https://github.com/pypa/sampleproject/issues",
    },
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    entry_points={'console_scripts': ["mytestscript1=my_package.script1:main", "mytestscript2=my_package.script2:main"]},
    python_requires=">=3.6"
)

app.spec that uses this script to work with setuptools

block_cipher = None


def Entrypoint(dist, group, name, **kwargs):
    import pkg_resources

    # get toplevel packages of distribution from metadata
    def get_toplevel(dist):
        distribution = pkg_resources.get_distribution(dist)
        if distribution.has_metadata('top_level.txt'):
            return list(distribution.get_metadata('top_level.txt').split())
        else:
            return []

    kwargs.setdefault('hiddenimports', [])
    packages = []
    for distribution in kwargs['hiddenimports']:
        packages += get_toplevel(distribution)

    kwargs.setdefault('pathex', [])
    # get the entry point
    ep = pkg_resources.get_entry_info(dist, group, name)
    # insert path of the egg at the verify front of the search path
    kwargs['pathex'] = [ep.dist.location] + kwargs['pathex']
    # script name must not be a valid module name to avoid name clashes on import
    script_path = os.path.join(workpath, name + '-script.py')
    print("creating script for entry point", dist, group, name)
    with open(script_path, 'w') as fh:
        print("import", ep.module_name, file=fh)
        print("%s.%s()" % (ep.module_name, '.'.join(ep.attrs)), file=fh)
        for package in packages:
            print("import", package, file=fh)

    return Analysis(
        [script_path] + kwargs.get('scripts', []),
        **kwargs
    )

a = Entrypoint("testapp", 'console_scripts', 'mytestscript1')
pyz = PYZ(a.pure, a.zipped_data)

exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='mytestscript1')

I first build the package using python3 -m build, Then I execute pyinstaller pyinstaller app.spec, Which results the following error:

27 INFO: PyInstaller: 4.10
27 INFO: Python: 3.8.10
34 INFO: Platform: Linux-5.10.60.1-microsoft-standard-WSL2-x86_64-with-glibc2.29
35 INFO: UPX is not available.
Traceback (most recent call last):
  File "/usr/local/bin/pyinstaller", line 8, in <module>
    sys.exit(run())
  File "/home/admin/.local/lib/python3.8/site-packages/PyInstaller/__main__.py", line 124, in run
    run_build(pyi_config, spec_file, **vars(args))
  File "/home/admin/.local/lib/python3.8/site-packages/PyInstaller/__main__.py", line 58, in run_build
    PyInstaller.building.build_main.main(pyi_config, spec_file, **kwargs)
  File "/home/admin/.local/lib/python3.8/site-packages/PyInstaller/building/build_main.py", line 803, in main
    build(specfile, distpath, workpath, clean_build)
  File "/home/admin/.local/lib/python3.8/site-packages/PyInstaller/building/build_main.py", line 725, in build
    exec(code, spec_namespace)
  File "app.spec", line 42, in <module>
    a = Entrypoint("testapp", 'console_scripts', 'mytestscript1', datas=[('testapp.egg-info/*','testapp.egg-info')])
  File "app.spec", line 25, in Entrypoint
    ep = pkg_resources.get_entry_info(dist, group, name)
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 500, in get_entry_info
    return get_distribution(dist).get_entry_info(group, name)
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 482, in get_distribution
    dist = get_provider(dist)
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 358, in get_provider
    return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0]
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 901, in require
    needed = self.resolve(parse_requirements(requirements))
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 787, in resolve
    raise DistributionNotFound(req, requirers)
pkg_resources.DistributionNotFound: The 'testapp' distribution was not found and is required by the application

The exception is invoked because pkg_resources.get_entry_info doesn't find my distribution when it is executed from pyinstaller, but when I run it from any normal script in the root it can be found without problems:

>>> import pkg_resources
>>> pkg_resources.get_entry_info("testapp", 'console_scripts', 'mytestscript1')
EntryPoint.parse('mytestscript1 = my_package.script1:main')

None of the solutions here helped!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我最亲爱的 2025-01-24 11:26:04

我认为我们可能遇到同样的问题。我具有与您相同的文件结构,包装名称的名称与代码所在的目录不同的内容(命名为testapp ),但目录命名为my_package)。我注意到,当我pip install我的软件包时,在site-packages egg> egg-info目录的名称(或> dist-info也许在您的情况下)是testapp_etc_.egg-info,源代码目录为my_package。我将其手动更改为mypackage_etc_.egg-infopkg_resources能够找到入口点。

我还应该提到,我不需要对.spec文件进行任何更改。我昨天凝视着Setuptools的食谱,并放弃了,我只是在使用pyinstaller时就使用了常规的命令行参数。最后,手动更改目录的名称不是这里的正确解决方案,我只是为了查看这是否是问题。实际解决方案是在setup.setup.setup()中更改软件包参数的名称。

I think we might be having the same problem. I have the same file structure as you, with the package name being named something different than the directory where the code is (package is named testapp but directory is named my_package). I noticed that when I'd pip install my package, in site-packages the name of the egg-info directory (or dist-info perhaps in your case) was testapp_etc_.egg-info and the source code directory was my_package. I manually changed it to mypackage_etc_.egg-info and pkg_resources was able to find the entry point.

I should also mention I did not require any changes to the .spec file. I stared at that Recipe for setuptools for a while yesterday and gave up on it, I just used my regular command line arguments when using pyinstaller. Lastly, manually changing the name of the directory is not the right solution here, I just did it to see if that was the issue. The actual solution would be to change the name of the package argument in setup.setup().

妳是的陽光 2025-01-24 11:26:04

这可能对任何人都没有帮助,但我的存储库使用的是我的主要 python 发行版中的 pyinstaller,直到我在我的 venv 中安装了 pyinstaller。然后我得到:

where pyinstaller
C:\dev\code\t3-revue\.venv\small\Scripts\pyinstaller.exe
C:\Users\xxx\AppData\Local\Programs\Python\Python311\Scripts\pyinstaller.exe

当它使用我的 venv 中的那个(我从中发出命令)时,它起作用了:

$ pwd
/c/dev/code/t3-revue
$ cls; pyinstaller config/installer/eyebrain.spec -y
-> no error

希望有帮助。

That may not help anybody, but my repo was using pyinstaller from my main python distribution, until I installed pyinstaller in my venv. Then I got:

where pyinstaller
C:\dev\code\t3-revue\.venv\small\Scripts\pyinstaller.exe
C:\Users\xxx\AppData\Local\Programs\Python\Python311\Scripts\pyinstaller.exe

When it used the one from my venv, from which I was issuing the command, it worked:

$ pwd
/c/dev/code/t3-revue
$ cls; pyinstaller config/installer/eyebrain.spec -y
-> no error

Hope that helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文