使用cx_Freeze制作的含googlesearch的Tkinter应用MSI运行异常
What's Going On Here?
You've built a solid subtitle downloader with Tkinter, using beautifulsoup and googlesearch, and cx_Freeze works perfectly for the loose build folder executable—but when you create an MSI installer with bdist_msi, the googlesearch.search() function breaks on fresh machines (even though it runs fine on your dev PC).
This is a common cx_Freeze gotcha: MSI packaging doesn't always capture all dynamic dependencies that the unstructured build folder does. Your dev machine has all the required Python libraries installed globally, so the MSI can fall back to those, but fresh machines don't have that safety net. Specifically, googlesearch uses dynamic imports (loads modules on-the-fly) that cx_Freeze's auto-detection misses, so those critical files aren't included in the MSI package.
Fixes to Try (Ordered by Ease)
1. Force Include All Dependencies in setup.py
cx_Freeze's auto-packaging might be skipping sub-modules that googlesearch relies on (like nested parts of requests). Update your packages list to explicitly include these:
import cx_Freeze import sys base = None if sys.platform == 'win32': base = "Win32GUI" executables = [cx_Freeze.Executable("subd.py", base=base, icon = "icon.ico")] cx_Freeze.setup( name = "SubD", author = "Mayank", options = { "build_exe":{ "packages":["tkinter","bs4","googlesearch","requests","requests.packages","requests.packages.urllib3","os"], "include_files":["icon.ico"] } }, version = "2.1", description = "Subtitle Downloader", executables = executables )
By explicitly listing these sub-packages, you're telling cx_Freeze to pack them regardless of its auto-detection limitations.
2. Bundle the Entire googlesearch Library Folder
If the first fix doesn't resolve the issue, you can force cx_Freeze to copy the full googlesearch directory from your local installation. Add code to find the library path and include it in include_files:
import cx_Freeze import sys import os import googlesearch base = None if sys.platform == 'win32': base = "Win32GUI" # Get the full path to the googlesearch library folder google_search_lib_path = os.path.dirname(googlesearch.__file__) executables = [cx_Freeze.Executable("subd.py", base=base, icon = "icon.ico")] cx_Freeze.setup( name = "SubD", author = "Mayank", options = { "build_exe":{ "packages":["tkinter","bs4","requests","os"], "include_files":[ "icon.ico", # Copy the googlesearch folder into the build/exe directory (google_search_lib_path, "googlesearch") ] } }, version = "2.1", description = "Subtitle Downloader", executables = executables )
This ensures every file in the googlesearch library is included in the MSI, eliminating gaps from dynamic imports.
3. Switch to a More Packager-Friendly Search Library
The unofficial googlesearch library can be finicky with packaging. For a more reliable long-term solution, consider:
- Using the official
google-api-python-client(requires a free Google API key) for legitimate, stable search access. - Scraping Google search results directly with
requestsandBeautifulSoup(just make sure to respect Google's robots.txt and rate limits).
4. Debug Missing Files
If you're still stuck, compare the contents of your build folder's lib directory with the MSI's installed lib folder on a fresh machine. Look for missing googlesearch or requests sub-files—once you identify what's missing, add it explicitly to include_files in setup.py.
How to Test
After updating setup.py, re-run:
python setup.py bdist_msi
Install the MSI on a machine with no pre-installed Python or related libraries, and test the search functionality to confirm it works.
内容的提问来源于stack exchange,提问作者Mayank Kumar Giri

