Andrew Ng机器学习专项课程Lab运行pyvirtualdisplay遇WinError2错误求助
问题:pyvirtualdisplay在Windows环境下运行报错FileNotFoundError
正在学习Andrew Ng的2022机器学习专项课程,在课程3第3周实验中执行以下代码:
from pyvirtualdisplay import Display Display(visible=0, size=(840, 480)).start();
在Jupyter中运行该单元格时出现如下错误:
FileNotFoundError Traceback (most recent call last) Input In [2], in <cell line: 2>() 1 # Set up a virtual display to render the Lunar Lander environment. ----> 2 Display(visible=0, size=(840, 480)).start(); 4 # Set the random seed for TensorFlow 5 tf.random.set_seed(utils.SEED) File D:\ProgramData\Anaconda3\envs\ML\lib\site-packages\pyvirtualdisplay\display.py:54, in Display.__init__(self, backend, visible, size, color_depth, bgcolor, use_xauth, retries, extra_args, manage_global_env, **kwargs) 51 if not cls: 52 raise ValueError("unknown backend: %s" % self._backend) ---> 54 self._obj = cls( 55 size=size, 56 color_depth=color_depth, 57 bgcolor=bgcolor, 58 retries=retries, 59 use_xauth=use_xauth, 60 # check_startup=check_startup, 61 extra_args=extra_args, 62 manage_global_env=manage_global_env, 63 **kwargs 64 ) File D:\ProgramData\Anaconda3\envs\ML\lib\site-packages\pyvirtualdisplay\xvfb.py:44, in XvfbDisplay.__init__(self, size, color_depth, bgcolor, use_xauth, fbdir, dpi, retries, extra_args, manage_global_env) 41 self._fbdir = fbdir 42 self._dpi = dpi ---> 44 AbstractDisplay.__init__( 45 self, 46 PROGRAM, 47 use_xauth=use_xauth, 48 retries=retries, 49 extra_args=extra_args, 50 manage_global_env=manage_global_env, 51 ) File D:\ProgramData\Anaconda3\envs\ML\lib\site-packages\pyvirtualdisplay\abstractdisplay.py:85, in AbstractDisplay.__init__(self, program, use_xauth, retries, extra_args, manage_global_env) 82 self._pipe_wfd = None 83 self._retries_current = 0 ---> 85 helptext = get_helptext(program) 86 self._has_displayfd = "-displayfd" in helptext 87 if not self._has_displayfd: File D:\ProgramData\Anaconda3\envs\ML\lib\site-packages\pyvirtualdisplay\util.py:13, in get_helptext(program) 6 cmd = [program, "-help"] 8 # py3.7+ 9 # p = subprocess.run(cmd, capture_output=True) 10 # stderr = p.stderr 11 12 # py3.6 also ---> 13 p = subprocess.Popen( 14 cmd, 15 stdout=subprocess.PIPE, 16 stderr=subprocess.PIPE, 17 shell=False, 18 ) 19 _, stderr = p.communicate() 21 helptext = stderr.decode("utf-8", "ignore") File D:\ProgramData\Anaconda3\envs\ML\lib\site-packages\subprocess.py:858, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, encoding, errors, text) 854 if self.text_mode: 855 self.stderr = io.TextIOWrapper(self.stderr, 856 encoding=encoding, errors=errors) ---> 858 self._execute_child(args, executable, preexec_fn, close_fds, 859 pass_fds, cwd, env, 860 startupinfo, creationflags, shell, 861 p2cread, p2cwrite, 862 c2pread, c2pwrite, 863 errread, errwrite, 864 restore_signals, start_new_session) 865 except: 866 # Cleanup if the child failed starting. 867 for f in filter(None, (self.stdin, self.stdout, self.stderr)): File D:\ProgramData\Anaconda3\envs\ML\lib\site-packages\subprocess.py:1311, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, unused_restore_signals, unused_start_new_session) 1309 # Start the process 1310 try: -> 1311 hp, ht, pid, tid = _winapi.CreateProcess(executable, args, 1312 # no special security 1313 None, None, 1314 int(not close_fds), 1315 creationflags, 1316 env, 1317 cwd, 1318 startupinfo) 1319 finally: 1320 # Child is launched. Close the parent's copy of those pipe 1321 # handles that only the child should have open. You need (...) 1324 # pipe will not close when the child process exits and the 1325 # ReadFile will hang. 1326 self._close_pipe_fds(p2cread, p2cwrite, 1327 c2pread, c2pwrite, 1328 errread, errwrite) FileNotFoundError: [WinError 2] The system cannot find the specified.
尝试修改subprocess.py源码将shell参数从False改为True,引发其他错误,不敢继续修改源码,寻求解决方案。
解决思路
1. 根本原因
pyvirtualdisplay默认依赖Xvfb后端,而Xvfb是Linux/Unix系统专属的虚拟X服务器,Windows系统原生不支持,这才是报错的核心,和subprocess的shell参数无关。
2. 可行方案
方案一:使用Windows兼容的虚拟显示后端
指定dummy后端绕过Xvfb调用,代码修改为:
from pyvirtualdisplay import Display Display(backend='dummy', visible=0, size=(840, 480)).start();
方案二:直接禁用虚拟显示(仅运行环境无需可视化)
如果实验只需要运行Lunar Lander环境、不需要渲染画面,可直接注释掉虚拟显示代码:
# 注释掉虚拟显示相关代码 # from pyvirtualdisplay import Display # Display(visible=0, size=(840, 480)).start(); # 继续后续实验代码 tf.random.set_seed(utils.SEED)
方案三:安装Windows版X服务器(需可视化场景)
- 安装VcXsrv Windows X服务器,启动时选择「Multiple windows」「Start no client」,勾选「Disable access control」
- 在Jupyter中添加环境变量配置后再调用pyvirtualdisplay:
import os os.environ['DISPLAY'] = ':0' # 与VcXsrv显示编号对应 from pyvirtualdisplay import Display Display(visible=0, size=(840, 480)).start();
3. 注意事项
- 不要修改subprocess源码,会破坏Python标准库稳定性,引发更多不可预知问题。
- 课程实验默认基于Linux环境设计,Windows用户需做适配调整。
内容的提问来源于stack exchange,提问作者yishifeng
相关产品推荐
相关产品推荐

