Skip to content

Inspect fails to retrieve module inside frozen app #342

@tumregels

Description

@tumregels

Description of the issue

when freezing playwright with pyinstaller the assertion in get_file_dirname fails

  File "main.py", line 6, in <module>
    with sync_playwright() as p:
  File "playwright/__init__.py", line 34, in sync_playwright
  File "playwright/main.py", line 81, in __init__
  File "playwright/main.py", line 76, in run_driver
  File "asyncio/base_events.py", line 587, in run_until_complete
  File "playwright/main.py", line 44, in run_driver_async
  File "playwright/main.py", line 36, in compute_driver_executable
  File "playwright/path_utils.py", line 23, in get_file_dirname
AssertionError

The reason is that the inspect module fails to find the module on the following lines inside get_file_dirname

frame = inspect.stack()[1]
module = inspect.getmodule(frame[0])

Context information

  • version of python: 3.7.9
  • version of pyinstaller: 4.1
  • version of playwright-python: Version 0.162.1
  • platform: GNU/Linux (Ubuntu 18.04 LTS)

Reproducing the bug

install packages

$ pip install playwright pyinstaller

install the browsers inside playwright

$ PLAYWRIGHT_BROWSERS_PATH=0 python -m playwright install

create main.py

# main.py
import sys
from pathlib import Path
from playwright import sync_playwright

with sync_playwright() as p:
    for browser_type in [p.chromium]:
        browser = browser_type.launch(
            headless=False,
            executablePath=Path(sys.modules['playwright'].__file__).parent / 'driver' / '.local-browsers' / 'chromium-827102' / 'chrome-linux' / 'chrome')
        page = browser.newPage()
        page.goto('http://whatsmyuseragent.org/')
        page.screenshot(path=f'example-{browser_type.name}.png')
        browser.close()

freeze into single binary file with pyinstaller

$ pyinstaller -F main.py --add-data /path/to/lib/python3.7/site-packages/playwright/driver:playwright/driver

execute the binary file

$ ./dist/main 
Traceback (most recent call last):
  File "main.py", line 6, in <module>
    with sync_playwright() as p:
  File "playwright/__init__.py", line 34, in sync_playwright
  File "playwright/main.py", line 81, in __init__
  File "playwright/main.py", line 76, in run_driver
  File "asyncio/base_events.py", line 587, in run_until_complete
  File "playwright/main.py", line 44, in run_driver_async
  File "playwright/main.py", line 36, in compute_driver_executable
  File "playwright/path_utils.py", line 23, in get_file_dirname
AssertionError

Proposed solution

The problem can be fixed by changing get_file_dirname with

import inspect
import sys
from pathlib import Path

def get_file_dirname() -> Path:
    """Returns the callee (`__file__`) directory name"""
    module_name = inspect.currentframe().f_back.f_globals["__name__"]
    module = sys.modules[module_name]
    assert module
    return Path(module.__file__).parent.absolute()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions