ronaldoussoren / py2app

py2app is a Python setuptools command which will allow you to make standalone Mac OS X application bundles and plugins from Python scripts.
Other
342 stars 36 forks source link

NotADirectoryError: [Errno 20] Not a directory #477

Open qiangshui opened 1 year ago

qiangshui commented 1 year ago

After executing python setup.py py2app, when I run ./dist/main.app/Contents/MacOS/main, I got this error :

NotADirectoryError: [Errno 20] Not a directory: '/Users/wj/myproject/client/dist/main.app/Contents/Resources/lib/python39.zip/playwright/driver/playwright.sh'

python39.zip is a compressed file, I find a related log in the build output: copying file build/bdist.macosx-10.9-x86_64/python3.9-standalone/app/python39.zip -> /Users/wj/myproject/client/dist/main.app/Contents/Resources/lib

It's running normally if I got the app file by python setup.py py2app -A .

system version: macOS Monterey 12.6 python: 3.9 py2app: 0.28.4

setup.py:

from setuptools import setup

APP = ['main.py']
DATA_FILES = []
OPTIONS = {}

setup(
    app=APP,
    data_files=DATA_FILES,
    options={'py2app': OPTIONS},
    setup_requires=['py2app'],
)
ronaldoussoren commented 1 year ago

Use OPTIONS = { "packages": ["playwright"] }, this will make sure that the "playwright" python package is kept outside of the zipfile.

BTW. Is "playwright" the PyPI package of the same name? If it is I can add a recipe to py2app that will do this automaticly.

qiangshui commented 1 year ago

Is "playwright" the PyPI package of the same name? If it is I can add a recipe to py2app that will do this automaticly.

Use OPTIONS = { "packages": ["playwright"] }, this will make sure that the "playwright" python package is kept outside of the zipfile.

BTW. Is "playwright" the PyPI package of the same name? If it is I can add a recipe to py2app that will do this automaticly.

Thanks for your replying. Yes, it's the same name.

After I use OPTIONS = { "packages": ["playwright"] }, I got an anothor error:

creating build/bdist.macosx-10.9-x86_64/python3.9-standalone/app/Frameworks
Traceback (most recent call last):
  File "/Users/wj/myproject/client/setup.py", line 14, in <module>
    setup(
  File "/Users/wj/miniconda3/envs/dsearch2/lib/python3.9/site-packages/setuptools/__init__.py", line 87, in setup
    return distutils.core.setup(**attrs)
  File "/Users/wj/miniconda3/envs/dsearch2/lib/python3.9/site-packages/setuptools/_distutils/core.py", line 185, in setup
    return run_commands(dist)
  File "/Users/wj/miniconda3/envs/dsearch2/lib/python3.9/site-packages/setuptools/_distutils/core.py", line 201, in run_commands
    dist.run_commands()
  File "/Users/wj/miniconda3/envs/dsearch2/lib/python3.9/site-packages/setuptools/_distutils/dist.py", line 968, in run_commands
    self.run_command(cmd)
  File "/Users/wj/miniconda3/envs/dsearch2/lib/python3.9/site-packages/setuptools/dist.py", line 1217, in run_command
    super().run_command(command)
  File "/Users/wj/miniconda3/envs/dsearch2/lib/python3.9/site-packages/setuptools/_distutils/dist.py", line 987, in run_command
    cmd_obj.run()
  File "/Users/wj/miniconda3/envs/dsearch2/lib/python3.9/site-packages/py2app/build_app.py", line 984, in run
    self._run()
  File "/Users/wj/miniconda3/envs/dsearch2/lib/python3.9/site-packages/py2app/build_app.py", line 1214, in _run
    self.run_normal()
  File "/Users/wj/miniconda3/envs/dsearch2/lib/python3.9/site-packages/py2app/build_app.py", line 1307, in run_normal
    mf = self.get_modulefinder()
  File "/Users/wj/miniconda3/envs/dsearch2/lib/python3.9/site-packages/py2app/build_app.py", line 1145, in get_modulefinder
    return find_modules(
  File "/Users/wj/miniconda3/envs/dsearch2/lib/python3.9/site-packages/modulegraph/find_modules.py", line 324, in find_modules
    find_needed_modules(mf, scripts, includes, packages)
  File "/Users/wj/miniconda3/envs/dsearch2/lib/python3.9/site-packages/modulegraph/find_modules.py", line 266, in find_needed_modules
    m = mf.import_hook(package, None, ["*"])
  File "/Users/wj/miniconda3/envs/dsearch2/lib/python3.9/site-packages/modulegraph/modulegraph.py", line 1134, in import_hook
    for s in self._ensure_fromlist(m, fromlist):
  File "/Users/wj/miniconda3/envs/dsearch2/lib/python3.9/site-packages/modulegraph/modulegraph.py", line 1264, in _ensure_fromlist
    raise ImportError("No module named " + fullname)
ImportError: No module named playwright._impl.__pyinstaller.hook-playwright.sync_api
ronaldoussoren commented 1 year ago

I get one step further with these options:


OPTIONS={
   "packages": ["playwright"],
   "excludes": ["playwright._impl.__pyinstaller.hook-playwright.sync_api", "playwright._impl.__pyinstaller.hook-playwright.async_api"]
}

That does not result in a completely working app bundle though: playwright complains it cannot locate the browser engine. Playwright outside of the app bundle installs those in a folder in ~/Library/Caches, but bundled in an app it looks for the inside the playwright package itself.

It might be possible to work around this problem manually by copying the browser engines manually after running pyapp, e.g. copy the contents of ~/Library/Caches/ms-playwright to main.app/Contents/Resources/lib/python3.9/playwright/driver/package/.local-browsers. That said, I tried this an this also causes problems (I get a traceback ending with the exception playwright._impl._api_types.Error: Target closed).

It seems that the playwright package has some assumptions about its runtime environment that aren't try in a bundles application. That's usually something that I can fix with a recipe in py2app, but researching that takes some time, and I don't have the time to do that research today.

To be continued...