我正在研究一个django项目。其中一个观点称为Popen()。大部分时间一切正常。但偶尔Popen()会因以下错误消息而失败:
Traceback (most recent call last):
File "C:\***\views.py", line 116, in process_request
proc = Popen(['python', exec_path, input_excel, current_tab, project])
File "C:\Python34\lib\subprocess.py", line 754, in __init__
_cleanup()
File "C:\Python34\lib\subprocess.py", line 474, in _cleanup
res = inst._internal_poll(_deadstate=sys.maxsize)
File "C:\Python34\lib\subprocess.py", line 1146, in _internal_poll
if _WaitForSingleObject(self._handle, 0) == _WAIT_OBJECT_0:
OSError: [WinError 6] The handle is invalid
重新启动服务器通常可以解决问题,但以后可能会再次显示。失败后立即尝试通常也会失败(用循环实现)。多次手动重新加载页面有时可以解决问题。
我也尝试了64位和32位python版本。问题显示在两者上。
似乎_cleanup()管理用于避免僵尸进程的_active列表。考虑到我在Windows上,我在Popen()中注释掉了_cleanup(),这似乎到目前为止工作正常。显然,这不是一个正确的解决方案。还有更好的主意吗?
更新
按照eryksun的建议,我仔细看了看手柄。由于某种原因,似乎django的autoreload.py关闭了进程句柄。请参阅下文了解详情。
---------------------------------------------------
try handle:
Handle(908)
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "C:\Python34\lib\site-packages\django\core\management\__init__.py", line 338, in execute_from_command_line
utility.execute()
File "C:\Python34\lib\site-packages\django\core\management\__init__.py", line 330, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\Python34\lib\site-packages\django\core\management\base.py", line 393, in run_from_argv
self.execute(*args, **cmd_options)
File "C:\Python34\lib\site-packages\django\core\management\commands\runserver.py", line 49, in execute
super(Command, self).execute(*args, **options)
File "C:\Python34\lib\site-packages\django\core\management\base.py", line 444, in execute
output = self.handle(*args, **options)
File "C:\Python34\lib\site-packages\django\core\management\commands\runserver.py", line 88, in handle
self.run(**options)
File "C:\Python34\lib\site-packages\django\core\management\commands\runserver.py", line 97, in run
autoreload.main(self.inner_run, None, options)
File "C:\Python34\lib\site-packages\django\utils\autoreload.py", line 325, in main
reloader(wrapped_main_func, args, kwargs)
File "C:\Python34\lib\site-packages\django\utils\autoreload.py", line 291, in python_reloader
reloader_thread()
File "C:\Python34\lib\site-packages\django\utils\autoreload.py", line 267, in reloader_thread
change = fn()
File "C:\Python34\lib\site-packages\django\utils\autoreload.py", line 204, in code_changed
for filename in gen_filenames():
File "C:\Python34\lib\site-packages\django\utils\autoreload.py", line 92, in gen_filenames
_cached_filenames = clean_files(_cached_filenames)
File "C:\Python34\lib\site-packages\django\utils\autoreload.py", line 139, in clean_files
if os.path.exists(filename):
File "C:\Python34\lib\genericpath.py", line 19, in exists
os.stat(path)
File "C:\Python34\lib\subprocess.py", line 452, in Close
print(traceback.print_stack())
None
handle closed.
---------------------------------------------------
以上修改产生以上错误信息。
def Close(self, CloseHandle=_winapi.CloseHandle):
print ('---------------------------------------------------')
print ('try handle:')
print (self)
if not self.closed:
self.closed = True
CloseHandle(self)
print(traceback.print_stack())
print ('handle closed.')
print ('---------------------------------------------------')
后来异常抱怨Handle(908)。 我无法理解os.stat(path)如何关闭句柄以及为什么该进程不会被subprocess.py从_active列表中删除。