下面是mod_wsgi文档中的代码:
from __future__ import print_function
import os
import sys
import time
import signal
import threading
import atexit
try:
import Queue as queue
except ImportError:
import queue
_interval = 1.0
_times = {}
_files = []
_running = False
_queue = queue.Queue()
_lock = threading.Lock()
def _restart(path):
_queue.put(True)
prefix = 'monitor (pid=%d):' % os.getpid()
print('%s Change detected to \'%s\'.' % (prefix, path), file=sys.stderr)
print('%s Triggering process restart.' % prefix, file=sys.stderr)
os.kill(os.getpid(), signal.SIGINT)
def _modified(path):
try:
# If path doesn't denote a file and were previously
# tracking it, then it has been removed or the file type
# has changed so force a restart. If not previously
# tracking the file then we can ignore it as probably
# pseudo reference such as when file extracted from a
# collection of modules contained in a zip file.
if not os.path.isfile(path):
return path in _times
# Check for when file last modified.
mtime = os.stat(path).st_mtime
if path not in _times:
_times[path] = mtime
# Force restart when modification time has changed, even
# if time now older, as that could indicate older file
# has been restored.
if mtime != _times[path]:
return True
except:
# If any exception occured, likely that file has been
# been removed just before stat(), so force a restart.
return True
return False
def _monitor():
while 1:
# Check modification times on all files in sys.modules.
for module in sys.modules.values():
print(module)
if not hasattr(module, '__file__'):
continue
path = getattr(module, '__file__')
if not path:
continue
if os.path.splitext(path)[1] in ['.pyc', '.pyo', '.pyd']:
path = path[:-1]
if _modified(path):
return _restart(path)
# Check modification times on files which have
# specifically been registered for monitoring.
for path in _files:
print(f'PATH: {path}')
if _modified(path):
return _restart(path)
# Go to sleep for specified interval.
try:
return _queue.get(timeout=_interval)
except:
pass
_thread = threading.Thread(target=_monitor)
_thread.setDaemon(True)
def _exiting():
try:
_queue.put(True)
except:
pass
_thread.join()
atexit.register(_exiting)
def track(path):
if path not in _files:
_files.append(path)
def start(interval=1.0):
global _interval
if interval < _interval:
_interval = interval
global _running
_lock.acquire()
if not _running:
prefix = 'monitor (pid=%d):' % os.getpid()
print('%s Starting change monitor.' % prefix, file=sys.stderr)
_running = True
_thread.start()
_lock.release()
这是我得到的错误:
[Thu Feb 23 18:46:27.482446 2023] [wsgi:error] [pid 11279] Exception in thread Thread-1 (_monitor):
[Thu Feb 23 18:46:27.482617 2023] [wsgi:error] [pid 11279] Traceback (most recent call last):
[Thu Feb 23 18:46:27.482635 2023] [wsgi:error] [pid 11279] File "/usr/lib64/python3.10/threading.py", line 1016, in _bootstrap_inner
[Thu Feb 23 18:46:27.482983 2023] [wsgi:error] [pid 11279] self.run()
[Thu Feb 23 18:46:27.483002 2023] [wsgi:error] [pid 11279] File "/usr/lib64/python3.10/threading.py", line 953, in run
[Thu Feb 23 18:46:27.483162 2023] [wsgi:error] [pid 11279] self._target(*self._args, **self._kwargs)
[Thu Feb 23 18:46:27.483177 2023] [wsgi:error] [pid 11279] File "/srv/flask_app/flask_app/monitor.py", line 66, in _monitor
[Thu Feb 23 18:46:27.483239 2023] [wsgi:error] [pid 11279] for module in sys.modules.values():
[Thu Feb 23 18:46:27.483263 2023] [wsgi:error] [pid 11279] RuntimeError: dictionary keys changed during iteration
这是我用来调用监视器的代码(当前):
monitor.start(interval=1.0)
for root, dirs, files in os.walk(os.path.dirname(__file__), topdown=False):
for name in files:
monitor.track(os.path.join(root, name))
我尝试了与作者建议的完全相同的代码,但也得到了同样的错误。
我不知道如何让它工作,因为我根本看不出为什么这是一个问题,在迭代过程中系统模块中发生了什么变化,为什么?
我试过改变要跟踪的文件,有时候一次加载就可以,有时候根本不起作用。我不知道我还能做什么tbh。似乎最好使用随机文件名,如'site.cy',作者在mod_wsgi文档中的默认示例中使用的。
1条答案
按热度按时间gjmwrych1#
复制sys.modules.values()似乎可以很好地进行迭代。