使用Pyinstaller编译含Selenium与Multiprocessing的Python脚本为EXE后无法运行
Pyinstaller打包含Selenium+Multiprocessing脚本无响应问题解决
以下是针对你遇到的打包后EXE无反应问题的具体解决步骤:
1. 修复多进程打包适配问题
Windows下Pyinstaller对multiprocessing的支持需要额外处理,否则会导致进程无法正常启动:
- 在
if __name__ == '__main__':代码块第一行添加multiprocessing.freeze_support() - 避免直接用
len(urls)设置进程数(可能因链接过多导致资源耗尽),建议设为CPU核心数或固定值(比如4)
2. 解决ChromeDriver路径依赖
打包后EXE无法直接找到chromedriver.exe,需处理路径并确保打包时包含驱动文件:
- 修改代码动态获取驱动路径:
然后将import sys import os def get_chromedriver_path(): if getattr(sys, 'frozen', False): # 打包后环境,取临时解压目录 base_path = sys._MEIPASS else: # 开发环境,取脚本所在目录 base_path = os.path.dirname(os.path.abspath(__file__)) return os.path.join(base_path, 'chromedriver.exe')webdriver.Chrome("chromedriver.exe", ...)替换为webdriver.Chrome(get_chromedriver_path(), ...) - 打包命令需添加驱动文件的打包参数(Windows):
pyinstaller --add-data "chromedriver.exe;." your_script.py
3. 开启控制台查看错误信息
如果之前用了-w参数打包(无窗口模式),会屏蔽所有报错输出,导致无法定位问题:
- 去掉
-w参数重新打包:pyinstaller your_script.py - 运行生成的EXE,通过控制台输出的错误信息排查具体问题
4. 优化Headless模式参数
旧版Headless模式可能存在兼容性问题,添加额外参数保证稳定运行:
options = webdriver.ChromeOptions() options.add_argument('--headless=new') # 使用新版Headless模式,兼容性更好 options.add_argument('window-size=1920x935') options.add_argument('--disable-gpu') options.add_argument('--no-sandbox') options.add_argument('--disable-dev-shm-usage')
5. 修复links.txt文件路径问题
打包后EXE的工作目录可能与脚本不同,需动态获取文件路径:
def get_links_path(): if getattr(sys, 'frozen', False): # 打包后取EXE所在目录 base_path = os.path.dirname(sys.executable) else: # 开发环境取脚本所在目录 base_path = os.path.dirname(os.path.abspath(__file__)) return os.path.join(base_path, 'links.txt') links = open(get_links_path(), encoding='utf-8', errors='ignore')
修改后的完整代码
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from multiprocessing import Pool, freeze_support import time import sys import os def get_chromedriver_path(): if getattr(sys, 'frozen', False): base_path = sys._MEIPASS else: base_path = os.path.dirname(os.path.abspath(__file__)) return os.path.join(base_path, 'chromedriver.exe') def get_links_path(): if getattr(sys, 'frozen', False): base_path = os.path.dirname(sys.executable) else: base_path = os.path.dirname(os.path.abspath(__file__)) return os.path.join(base_path, 'links.txt') def start(url): url = url.strip() # 去除链接中的换行符,避免无效请求 options = webdriver.ChromeOptions() options.add_argument('--headless=new') options.add_argument('window-size=1920x935') options.add_argument('--disable-gpu') options.add_argument('--no-sandbox') options.add_argument('--disable-dev-shm-usage') browser = webdriver.Chrome(get_chromedriver_path(), options=options) wait = WebDriverWait(browser, 10) try: browser.get(url) browser.switch_to.window(browser.window_handles[-1]) wait.until(EC.visibility_of_element_located((By.XPATH, '//*[@id="movie_player"]/div[33]/div[2]/div[1]/button'))).click() wait.until(EC.visibility_of_element_located((By.XPATH, '//*[@id="movie_player"]/div[33]/div[2]/div[1]/span/button'))).click() time.sleep(180) except Exception as e: print(f"处理链接 {url} 时出错: {e}") finally: browser.quit() if __name__ == '__main__': freeze_support() # 必须放在多进程启动前 urls = [] try: with open(get_links_path(), encoding='utf-8', errors='ignore') as links: urls = [line.strip() for line in links if line.strip()] # 过滤空行并去除换行 if not urls: print("links.txt中无有效链接") sys.exit(1) # 限制进程数为CPU核心数或固定值,避免资源耗尽 process_count = min(len(urls), os.cpu_count() or 4) with Pool(processes=process_count) as p: p.map(start, urls) except Exception as e: print(f"程序初始化出错: {e}") input("按回车退出...") # 打包后控制台不会自动关闭,方便查看错误
内容的提问来源于stack exchange,提问作者NIKITA
相关产品推荐
相关产品推荐

