diff --git a/binblog/settings_example.py b/binblog/settings_example.py index bcb9ece..f53e9b7 100644 --- a/binblog/settings_example.py +++ b/binblog/settings_example.py @@ -23,6 +23,7 @@ # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True +LOCAL_DEBUG = True # 本地代理static和media可以使用命令python manage.py runserver --insecure ALLOWED_HOSTS = ['*'] @@ -62,6 +63,15 @@ 'blog.middleware.LoadTimeMiddleware' # 页面加载时间 ] +# 是否启用django-debug-toolbar. 需要安装: pip install django-debug-toolbar +DJANGO_DEBUG_TOOLBAR = False # 自己定义的变量, 在urls.py里也需要引入相关路由 +if DJANGO_DEBUG_TOOLBAR: # 还有另一种 django-silk可以尝试用 + # debug工具, 只有在debug=True才生效, 开发环境内使用, 其实可以抽多个settings.develop.py + INTERNAL_IPS = ['127.0.0.1'] + INSTALLED_APPS += ['debug_toolbar', ] + MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware', ] + # DEBUG_TOOLBAR_PANELS = [] # 可以自己找更多的插件用 + ROOT_URLCONF = 'binblog.urls' TEMPLATES = [ diff --git a/binblog/urls.py b/binblog/urls.py index 9deb488..e5f3f36 100644 --- a/binblog/urls.py +++ b/binblog/urls.py @@ -1,5 +1,5 @@ from django.contrib import admin -from django.urls import path, include +from django.urls import path, include, re_path from django.conf.urls.static import static from django.contrib.sitemaps.views import sitemap from django.conf import settings @@ -46,7 +46,30 @@ path('refresh/', refresh_cache, name='refresh'), ] -urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) +if settings.DEBUG: + # 线上模式需要使用nginx来代理这些静态资源, static()其实return了一个 [re_path()对象] + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + + if settings.DJANGO_DEBUG_TOOLBAR: + # 例如在sql面板中可以看到重复执行的sql语句, 借此可以优化自己的系统 + import debug_toolbar + + urlpatterns += [path('__debug__/', include(debug_toolbar.urls)), ] + +if not settings.DEBUG and settings.LOCAL_DEBUG: + # 本地想调试线上环境可以使用 --insecure参数 Allows serving static files even if DEBUG is False. + # python manage.py runserver --insecure + # 上面的 static()方法在DEBUG=False时是return [], 不会serve media, 可以这样写用于media + + # from django.views.static import serve + # from django.urls import re_path + # urlpatterns += [re_path(r'^media/(?P.*$)', serve, {'document_root': settings.MEDIA_ROOT}), ] + # 上面这行又可以仿照static()里的实现, lstrip('/')去掉字符串左边'/' + from django.views.static import serve + import re + + urlpatterns += [re_path(r'^%s(?P.*$)' % re.escape(settings.MEDIA_URL.lstrip('/')), + serve, {'document_root': settings.MEDIA_ROOT}), ] # 全局403 404 500设置 handler403 = 'blog.views.permission_denied' diff --git a/log/binblog_error.log b/log/binblog_error.log index 5e41dd7..4241552 100644 --- a/log/binblog_error.log +++ b/log/binblog_error.log @@ -18,3 +18,128 @@ [2019-06-26 16:13:11,439] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': '彬彬冲呀66666666'} [2019-06-26 16:13:57,928] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': '彬彬冲呀66666666'} [2019-06-26 16:14:53,794] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': '彬彬冲呀66666666'} +[2019-06-28 09:29:24,112] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:29:24,284] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/favicon.ico'} +[2019-06-28 09:29:25,815] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:29:26,486] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:29:26,963] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:29:27,371] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:29:27,928] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:29:28,417] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:29:31,036] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:29:33,154] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:30:12,623] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:30:13,895] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:30:14,580] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:30:18,263] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:30:19,257] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:32:26,552] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 09:32:26,555] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 09:32:26,684] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:32:27,435] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/favicon.ico'} +[2019-06-28 09:33:00,118] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:33:36,284] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:33:37,259] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:33:37,881] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:33:40,995] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:33:49,451] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:33:50,124] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:33:50,608] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:34:17,579] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:37:23,618] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:37:24,302] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:38:15,600] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:40:41,760] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:40:42,566] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:40:43,744] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:40:45,372] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:40:46,516] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:40:47,382] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:40:48,836] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:40:53,479] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:42:54,223] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:42:54,916] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:42:55,481] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:43:02,496] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:43:07,907] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:43:11,273] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:43:13,947] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:43:17,519] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:43:18,382] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:43:18,896] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:43:45,961] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:52:24,351] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:52:26,595] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:59:13,115] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:59:16,016] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:59:22,217] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:59:22,974] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:59:36,836] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:59:38,081] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 09:59:38,718] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 10:01:21,196] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 10:02:58,144] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 10:03:19,391] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 10:03:20,078] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 10:03:20,896] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 10:28:04,832] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 10:28:04,833] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 10:28:06,132] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 10:28:06,134] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 10:28:06,427] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/favicon.ico'} +[2019-06-28 10:28:10,720] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 10:28:10,721] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 10:28:11,038] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/favicon.ico'} +[2019-06-28 10:28:29,376] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 10:28:29,377] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 10:31:09,215] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 10:31:09,217] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 10:31:12,459] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 10:31:12,460] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 10:31:12,751] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/favicon.ico'} +[2019-06-28 10:31:51,646] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 10:31:51,647] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 10:32:15,148] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 10:32:15,225] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 10:32:16,172] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 10:32:16,185] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 10:32:16,467] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/favicon.ico'} +[2019-06-28 10:37:01,203] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 10:37:01,203] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 10:37:01,206] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 10:37:01,499] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/favicon.ico'} +[2019-06-28 10:38:09,067] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 10:38:09,071] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 10:38:09,271] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/favicon.ico'} +[2019-06-28 10:38:10,201] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 10:38:10,203] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 10:38:19,892] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 10:38:19,930] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 10:38:21,088] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 10:38:21,092] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 10:38:24,767] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 10:38:24,769] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 10:38:25,081] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/favicon.ico'} +[2019-06-28 10:40:13,416] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 10:40:13,423] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 10:40:14,353] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/favicon.ico'} +[2019-06-28 10:42:09,387] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 10:44:18,975] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'media/photo/asfs.png'} +[2019-06-28 11:00:55,416] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/favicon.ico'} +[2019-06-28 11:00:56,432] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 11:00:56,438] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 11:00:56,657] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/favicon.ico'} +[2019-06-28 11:00:57,419] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 11:00:57,423] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 11:00:57,643] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/favicon.ico'} +[2019-06-28 11:01:28,252] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 11:01:28,253] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 11:01:41,779] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 11:01:41,779] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 11:01:44,269] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 11:01:44,273] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 11:01:44,500] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/favicon.ico'} +[2019-06-28 11:10:34,419] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/favicon.ico'} +[2019-06-28 11:10:53,684] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/css/4dae8f1035d4.css'} +[2019-06-28 11:10:53,687] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/CACHE/js/b3ecec28477c.js'} +[2019-06-28 11:10:53,912] ERROR [blog.views.page_not_found:297 views] {'status': '404', 'path': 'static/favicon.ico'} diff --git a/utils/my_lrucache.py b/utils/my_lrucache.py new file mode 100644 index 0000000..3128f2d --- /dev/null +++ b/utils/my_lrucache.py @@ -0,0 +1,121 @@ +import time +from collections import OrderedDict # 一个有序的Dict +from functools import wraps + + +class LRUCacheDict(object): + # py3: from functools import lru_cache + def __init__(self, max_size=1024, expiration=60): + self.max_size = max_size # 最大容量, 1024个key + self.expiration = expiration # 单个key有效期60秒 + self._cache = {} # LRU缓存 (Least Recently Used 近期最少使用) + self._access_time = OrderedDict() # 记录访问时间 + self._expire_time = OrderedDict() # 记过过期时间 + + def __setitem__(self, key, value): + """ 设置缓存, 调用obj[key] = value执行 """ + now = int(time.time()) + self.__delitem__(key) # 删除当前key + + self._cache[key] = value + self._access_time[key] = now + self._expire_time[key] = now + self.expiration + self.cleanup() + + def __getitem__(self, key): + """ 获取缓存中key对应的value, 调用obj['key']执行 """ + now = int(time.time()) + del self._access_time[key] + + self._access_time[key] = now + self.cleanup() + + return self._cache[key] + + def __delitem__(self, key): + """ 调用 del obj['key']时候执行 """ + if key in self._cache: + del self._cache[key] + del self._access_time[key] + del self._expire_time[key] + + def __contains__(self, key): + """ 当前缓存中是否有这个key, 当调用key in obj会执行 """ + self.cleanup() + return key in self._cache + + def cleanup(self): + """ 清理过期或者超过大小的缓存 """ + if self.expiration is None: + return None # 没设置过期时间就不清理 + + now = int(time.time()) + pending_del_keys = [] # 存储待删除的key + + # 记录过期缓存key + for key, value in self._expire_time.items(): + if value < now: + pending_del_keys.append(key) + + # 删除过期缓存key, 因为不能在上面迭代过程中删除 + for del_key in pending_del_keys: + self.__delitem__(del_key) + + # 超过容量, 删除最旧的缓存 + while len(self._cache) > self.max_size: + for key in self._access_time: + self.__delitem__(key) + break + + def size(self): + """ 返回缓存长度 """ + return len(self._cache) + + def clear(self): + """ 清理所有缓存 """ + self._cache.clear() + self._access_time.clear() + self._expire_time.clear() + + +def cache_it(max_size=1024, expiration=60): + cache = LRUCacheDict(max_size, expiration) + + def wrapper(func): + @wraps(func) + def inner(*args, **kwargs): + key = repr(*args, **kwargs) + try: + result = cache[key] + except KeyError: + result = func(*args, **kwargs) + cache[key] = result + return result + + return inner + + return wrapper + + +@cache_it(max_size=2, expiration=2) +def test(num): + time.sleep(1) # 睡一秒, 只有第一次没缓存的时候慢 + res = 'this is number %s' % num + return res + + +if __name__ == '__main__': + cache_dict = LRUCacheDict(max_size=3, expiration=1) + cache_dict['name'] = 'binbin' + cache_dict['age'] = '22' + cache_dict['gender'] = 'male' + cache_dict['other'] = 'null' + + print('name' in cache_dict) # False, 超过最大容量, 最旧的记录被删除了 + print('other' in cache_dict) # True + time.sleep(1.5) + print('other' in cache_dict) # Fasle, 过期记录被删除了 + + print(test(2)) + print(test(3)) + print(test(2)) # 这里就直接用到了缓存, 没有sleep(1)