Inspect fails to retrieve module inside frozen app
See original GitHub issueDescription 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()
Issue Analytics
- State:
- Created 3 years ago
- Comments:7 (2 by maintainers)
Top Results From Across the Web
Inspect module issues in pyinstaller frozen app
I have frozen pwrapper.py using pyinstaller. When I launch pwrapper.exe from command line, everything works fine. I get the output
Read more >When Things Go Wrong — PyInstaller 5.7.0 documentation
When you run the bundled app and it terminates with an ImportError, that is the time to examine the warning file. Then see...
Read more >Troubleshooting guide
Use the Access Gateway troubleshooting guide to resolve issues with your organization's Access Gateway deployment.
Read more >TorchScript — PyTorch 1.13 documentation
Module will inspect the source code, compile it as TorchScript code using the TorchScript compiler, and return a ScriptModule or ScriptFunction .
Read more >Command-line API | Node.js v19.3.0 Documentation
This does not affect the Node.js node:vm module. ... --frozen-intrinsics # ... specifies the path to the blob that is used to restore...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Hopefully this can help anyone struggling to compile a Playwright script with Pyinstaller.
Here is how I have managed to make a template for compiling a Playwright script with Pyinstaller on Windows.
A basic main.py:
A compile.bat to automate the install and Pyinstaller process:
Cheers.
I PROPOSE ANOTHER SOLUTION
I use Windows 10. I tried pavelfeldman solution…
Did not work! I don’t think I understand the correct way to do this in Windows.
I tried the mbalslow solution and it worked! However, the basic file, which was 8.52 MB, ended up being 137 MB, which, of course, I was not satisfied with.
I have a lot of professional applications (that I make to sell) that I use selenium. And they are on average 14 MB in size. Because, the way that I make, my application does not load the binaries. She installs the binaries on the client’s computer, and uses them. That’s why I get such a lean application, using the following method:
That’s when I thought, “What if, like with selenium, I didn’t need to load the binaries into my executable? What if I could just install them on first run on my client’s computer, and then use it in cache like me do with selenium?”
So I started looking for a way to install the binaries through playwright, in a folder on my client, and use that in my application as a cache. But I didn’t find such a solution (Maybe there is, and I’ve just been unable to find it).
And then came another idea: “I currently only develop applications for Windows. Practically every Windows nowadays has: either a Microsoft Edge, or a Google Chrome, or a Firefox. What if I just take the directory of those browsers, and use them?”
So, I developed a way to get, from the windows registry, one of the directories of the browsers binaries, installed on the computer, and then, tell playwright to use it (not done in firefox yet, but it is possible to do):
This is an amateur solution made by me, to try to get around the problem. Maybe later it will be possible to do in a more optimized way, this idea of taking the binaries that already exist in the system, and just using them. Don’t take into account the form made, but the idea behind it.
So, putting in focus, the heart the idea is: Use the binaries already existing in the system, just pointing to them!
CONCLUSION: When I run this code through PyCharm it works perfectly! When I compile with Pyinstaller, and run it, I get the following error in my log.log file (because I catch the error, and Write it in a file)
I can’t understand why this works in PyCharm, and not with PyInstaller, since the directory, as you can see in the log.log, is correct! Why doesn’t it work in PyInstaller, if I’m pointing correctly to the binary directory?
I believe it is a great idea/solution to be officially applied to the tool: to give the option to use the binaries that already exist on the computer. I just haven’t been able to execute it perfectly yet. Does anyone have any ideas? Did you see my mistake?
Sources Files: source.zip
Thanks for your patience and attention…