PyInstaller打包subprocess调用netsh脚本报WinError6句柄无效如何解决
报错原因
这个OSError: [WinError 6] 句柄无效错误的触发逻辑非常明确:
- 你本次使用PyInstaller打包时添加了
--windowed(或-w/--noconsole)无控制台窗口参数,这种模式下Python进程不会分配标准输入、输出、错误流的对应句柄。 - 代码中调用
subprocess.run时默认会继承父进程的标准流句柄,找不到对应句柄就会抛出该错误。 - 之前打包能正常运行,是因为此前打包未添加无控制台参数,使用默认控制台模式的进程有完整的标准流句柄。
修复方案
根据是否需要隐藏运行时的黑框窗口,有两种可选修复方式:
方案1:使用控制台模式打包
不需要隐藏运行窗口的话,打包时直接去掉--windowed/-w/--noconsole参数,用默认配置打包即可正常运行。
方案2:修改subprocess调用适配无控制台模式
需要隐藏控制台窗口的话,给所有subprocess.run调用加上stdin=subprocess.DEVNULL参数,显式指定子进程的标准输入为空,不要继承父进程不存在的句柄即可。
修改后的完整代码如下:
import subprocess import time import sys import re command_output = subprocess.run(["netsh", "wlan", "show", "profiles"], capture_output = True, stdin=subprocess.DEVNULL).stdout.decode() profile_names = (re.findall("All User Profile : (.*)\r", command_output)) wifi_list = [] if len(profile_names) != 0: for name in profile_names: wifi_profile = {} profile_info = subprocess.run(["netsh", "wlan", "show", "profile", name], capture_output = True, stdin=subprocess.DEVNULL).stdout.decode() if re.search("Security key : Absent", profile_info): continue else: wifi_profile["ssid"] = name profile_info_pass = subprocess.run(["netsh", "wlan", "show", "profile", name, "key=clear"], capture_output = True, stdin=subprocess.DEVNULL).stdout.decode() password = re.search("Key Content : (.*)\r", profile_info_pass) if password == None: wifi_profile["password"] = None else: wifi_profile["password"] = password[1] wifi_list.append(wifi_profile) for x in range(len(wifi_list)): print(wifi_list[x]) time.sleep(5) print("No more WiFi Profiles Found") time.sleep(3) sys.exit()
修改后再用--windowed参数打包即可正常运行。
内容的提问来源于stack exchange,提问作者Chameleon
相关产品推荐
相关产品推荐

