代码拉取完成,页面将自动刷新
同步操作将从 xupingmao/xnote 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
# encoding=utf-8
"""Xnote自动加载
autoreload会自动搜索指定目录下的文件
一旦修改时间发生变化会立即触发回调函数
"""
from threading import Thread
import time
import subprocess
import sys
import types
import os
import sys
import traceback
BLOCKED_EXT_LIST = [".pyc", ".class"]
_has_execv = sys.platform != 'win32'
_watched_files = []
_reload_trys = []
_callbacks = []
_reload_attempt = False
def print_exception(e):
ex_type, ex, tb = sys.exc_info()
print(ex)
traceback.print_tb(tb)
def force_reload():
_reload_attempt = True
class ReloadError(Exception):
pass
class AutoReloadThread(Thread):
def __init__(self, *callbacks):
global _callbacks
super(AutoReloadThread, self).__init__(name="AutoReloadThread")
self.setDaemon(True)
self.interval = 0.5
self.watched_dirs = []
for callback in callbacks:
_callbacks.append(callback)
def watch_dir(self, dir, recursive=False):
if recursive:
self.watch_recursive_dir(dir)
return
self.watched_dirs.append(dir)
_check_watch_dirs(self.watched_dirs)
def watch_file(self, filepath):
global _watched_files
path = os.path.abspath(filepath)
_watched_files.append(path)
def watch_recursive_dir(self, dir):
for root, dirs, files in os.walk(dir):
for filename in files:
abspath = os.path.join(root, filename)
name, ext = os.path.splitext(filename)
if ext in BLOCKED_EXT_LIST:
continue
if abspath not in _watched_files:
_watched_files.append(abspath)
def clear_watched_files(self):
global _watched_files
_watched_files = []
def run(self):
global _reload_attempt
modify_times = {}
while True:
try:
_reload_on_update(modify_times)
except ReloadError as e:
# 通过抛出一个ReloadError来通知重新加载
modify_times = {}
for callback in _callbacks:
callback()
time.sleep(self.interval)
def _check_watch_dirs(watched_dirs):
for dir in watched_dirs:
_check_watch_dir(dir)
def _check_watch_dir(dir):
global _watched_files
for file in os.listdir(dir):
path = os.path.join(dir, file)
if path not in _watched_files:
_watched_files.append(path)
def check_sys_modules(modify_times):
for module in list(sys.modules.values()):
# Some modules play games with sys.modules (e.g. email/__init__.py
# in the standard library), and occasionally this can cause strange
# failures in getattr. Just ignore anything that's not an ordinary
# module.
if not isinstance(module, types.ModuleType):
continue
path = getattr(module, "__file__", None)
if not path:
continue
if path.endswith(".pyc") or path.endswith(".pyo"):
path = path[:-1]
_check_file(modify_times, path)
def _reload_on_update(modify_times):
for path in _watched_files:
_check_file(modify_times, path)
def _check_file(modify_times, path):
try:
modified = os.stat(path).st_mtime
except Exception as e:
print_exception(e)
if path in _watched_files:
_watched_files.remove(path)
return
if path not in modify_times:
modify_times[path] = modified
return
if modify_times[path] != modified:
print("file %s modified, reload" % path)
raise ReloadError()
def reload():
for fn in _callbacks:
fn()
def _reload():
# sys.path fixes: see comments at top of file. If sys.path[0] is an empty
# string, we were (probably) invoked with -m and the effective path
# is about to change on re-exec. Add the current directory to $PYTHONPATH
# to ensure that the new process sees the same path we did.
path_prefix = '.' + os.pathsep
if (sys.path[0] == '' and
not os.environ.get("PYTHONPATH", "").startswith(path_prefix)):
os.environ["PYTHONPATH"] = (path_prefix +
os.environ.get("PYTHONPATH", ""))
# call stop hooks
for fn in _callbacks:
fn()
# return, just call the callbacks
force_reload()
return
if not _has_execv:
subprocess.Popen([sys.executable] + sys.argv)
# os.popen(sys.executable + " " + " ".join(sys.argv))
print("restart server")
sys.exit(0)
else:
try:
os.execv(sys.executable, [sys.executable] + sys.argv)
except OSError:
# Mac OS X versions prior to 10.6 do not support execv in
# a process that contains multiple threads. Instead of
# re-executing in the current process, start a new one
# and cause the current process to exit. This isn't
# ideal since the new process is detached from the parent
# terminal and thus cannot easily be killed with ctrl-C,
# but it's better than not being able to autoreload at
# all.
# Unfortunately the errno returned in this case does not
# appear to be consistent, so we can't easily check for
# this error specifically.
os.spawnv(os.P_NOWAIT, sys.executable,
[sys.executable] + sys.argv)
# At this point the IOLoop has been closed and finally
# blocks will experience errors if we allow the stack to
# unwind, so just exit uncleanly.
os._exit(0)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。