diff --git a/.gitignore b/.gitignore index 9d3fd5354d181b9ba0d09e81b2d502aeef37d292..2e9777372bd4eead102db1a21306fffb2e3ee2dd 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,6 @@ __pycache__ /.vscode /dist /kcweb.egg-info -/file \ No newline at end of file +/file +/utill/Queues +/utill/db/sqlitedata/kcwlicuxweb \ No newline at end of file diff --git a/README.md b/README.md index d9f599cc40505fdb1ce59efa4e9333512d2cd161..7dee6dd9b198d69f9dc93c34c6ad9647cf5e8914 100644 --- a/README.md +++ b/README.md @@ -34,11 +34,6 @@ create("app","api") # 创建项目 │ │ │ │ ├─index │ │ │ │ │ ├─index.html 模块文件 │ │ ├─__init__.py 控制器初始化文件 -│ ├─script 命令行脚本 -│ │ ├─common 该模块的公共函数目录 -│ │ │ ├─__init__.py 函数文件 -│ │ │ ├─win.py 类文件 -│ │ ├─test.py 脚本文件 │ ├─static 静态资源目录 │ ├─runtime 缓存目录 │ ├─__init__.py 自动导入模块文件 diff --git a/app.py b/app.py index 087055bcc1748b18054a83fc5954bff0f264fb78..53cb0759a7ab085228a95c7cd752f7f929215c40 100644 --- a/app.py +++ b/app.py @@ -53,7 +53,10 @@ class web: ] else: status,resheader,body=self.__routes(self,env) - body=bytes(body, encoding='utf-8') + if type(body) is bytes: + pass + else: + body=bytes(body, encoding='utf-8') # print(env['bodydata']) # print("\n\nwsgi.input",env['wsgi.input']) # print("\n\ndir(env['wsgi.input'])",dir(env['wsgi.input'])) @@ -295,21 +298,22 @@ class web: i+=1 else: #完全默认 routedefault,PATH_INFO=web.__getconfigroute(self,PATH_INFO,header) - for path in PATH_INFO: - if path: - if i==0: - modular=path - elif i==1: - edition=path - elif i==2: - files=path - urls=urls+"/"+str(path) - elif i==3: - funct=path - urls=urls+"/"+str(path) - else: - param.append(urllib.parse.unquote(path)) - i+=1 + if routedefault: #使用默认路由 + for path in PATH_INFO: + if path: + if i==0: + modular=path + elif i==1: + edition=path + elif i==2: + files=path + urls=urls+"/"+str(path) + elif i==3: + funct=path + urls=urls+"/"+str(path) + else: + param.append(urllib.parse.unquote(path)) + i+=1 #默认路由end ############################################################ return methods,modular,edition,files,funct,tuple(param) def __tran(self,data,status,resheader): @@ -356,7 +360,7 @@ class web: resheader={"Content-Type":"text/html; charset=utf-8"} web.__set_globals(self,header) PATH_INFO=header['PATH_INFO'].split('/') - if PATH_INFO[0]==' ': + if PATH_INFO[0]==' ' or PATH_INFO[0]=='': del PATH_INFO[0] methods,modular,edition,files,funct,param=web.defaultroute(self,header,PATH_INFO) if header['REQUEST_METHOD'] in methods: @@ -575,7 +579,11 @@ class web: if isinstance(resheaders,list): if not body: body='' - return str(status),resheaders,str(body) + if type(body) is bytes: + pass + else: + body=str(body) + return str(status),resheaders,body else: raise Exception() def __tpl(**context): @@ -680,7 +688,10 @@ class web: header+="Content-Length:%d\n" % len(body) else: status,resheader,body=self.__routes(reqheader) - body=body.encode() + if type(body) is bytes: + pass + else: + body=body.encode() header="HTTP/1.1 %s \n" % status header+="Content-Length:%d\n" % len(body) diff --git a/application/api/common/__init__.py b/application/api/common/__init__.py index 33d1e0db64a960643bed84d644d7ea0000eb00e5..0917cdf745c2cfe170f5abb0824e4a7e856bb560 100644 --- a/application/api/common/__init__.py +++ b/application/api/common/__init__.py @@ -1,7 +1,5 @@ # -*- coding: utf-8 -*- -from ${appname}.common import * -#下面的方法在当前模块中有效 -G=globals.G +from .autoload import * #下面的方法在当前模块中有效 def before_request(): G.userinfo=get_session("userinfo") diff --git a/application/api/common/autoload.py b/application/api/common/autoload.py new file mode 100644 index 0000000000000000000000000000000000000000..05965c2340f62dc7443ee92d6f93b682ff11a160 --- /dev/null +++ b/application/api/common/autoload.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +from ${appname}.common import * \ No newline at end of file diff --git a/application/common/__init__.py b/application/common/__init__.py index 39b5f600a86fac06052c3ab1091cbb6468e87b3b..05e1c79183f97ed6c558b5b16f304ec1b2b2028f 100644 --- a/application/common/__init__.py +++ b/application/common/__init__.py @@ -1,7 +1,5 @@ # -*- coding: utf-8 -*- -from kcweb.common import * -from ${appname} import config -import math +from .autoload import * def return_list(lists,count,pagenow,pagesize): """返回分页列表 diff --git a/application/common/autoload.py b/application/common/autoload.py new file mode 100644 index 0000000000000000000000000000000000000000..99a5719f40b0d4ac4e496f5ef6ed4707dc9593ab --- /dev/null +++ b/application/common/autoload.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +from kcweb.common import * +from ${appname} import config +import math,random +G=globals.G \ No newline at end of file diff --git a/common/autoload.py b/common/autoload.py index 651236738efe01e47f437be1e1c5457ff0911825..4b917d1dab2a1e817b4a1288ea9008cb37743f05 100644 --- a/common/autoload.py +++ b/common/autoload.py @@ -9,16 +9,28 @@ from kcweb.utill.db import sqlite as kcwsqlite from kcweb.utill.cache import cache as kcwcache from kcweb.utill.redis import redis as kcwredis from kcweb.utill.http import Http +from kcweb.utill.queues import Queues from kcweb.utill.db import model from mako.template import Template as kcwTemplate - import smtplib from email.mime.text import MIMEText from email.utils import formataddr from . import globals + redis=kcwredis() def send_mail(user,text="邮件内容",theme="邮件主题",recNick="收件人昵称"): - "发送邮件" + """发送邮件 + + 参数 user:接收邮件的邮箱地址 + + 参数 text:邮件内容 + + 参数 theme:邮件主题 + + 参数 recNick:收件人昵称 + + return Boolean类型 + """ ret=True if not theme: theme=config.email['theme'] @@ -39,8 +51,11 @@ def send_mail(user,text="邮件内容",theme="邮件主题",recNick="收件人 return ret get_sysinfodesffafew=None def get_sysinfo(): + """获取系统信息 + + return dict类型 + """ global get_sysinfodesffafew - "获取系统信息" if get_sysinfodesffafew: sysinfo=get_sysinfodesffafew else: @@ -94,7 +109,7 @@ def sqlite(table=None,configss=None): 参数 table:表名 - 参数 config 数据库配置 可以传数据库名字符串 + 参数 configss 数据库配置 可以传数据库名字符串 """ dbs=kcwsqlite.sqlite() if table is None: @@ -108,7 +123,7 @@ def M(table=None,confi=None): 参数 table:表名 - 参数 config 数据库配置 可以传数据库名字符串 + 参数 confi 数据库配置 可以传数据库名字符串 """ if confi: if confi['type']=='sqlite': @@ -136,9 +151,12 @@ def mongo(table=None,configss=None): return mObj.connect(config.mongo).table(table) def is_index(params,index): """判断列表或字典里的索引是否存在 + params 列表或字典 + index 索引值 - return True/False + + return Boolean类型 """ try: params[index] @@ -151,35 +169,47 @@ def is_index(params,index): def set_cache(name,values,expire="no"): """设置缓存 - 参数 name:缓存名 + 参数 name:缓存名 - 参数 values:缓存值 + 参数 values:缓存值 - 参数 expire:缓存有效期 0表示永久 单位 秒 - - return Boolean类型 - """ + 参数 expire:缓存有效期 0表示永久 单位 秒 + + return Boolean类型 + """ return kcwcache.cache().set_cache(name,values,expire) def get_cache(name): """获取缓存 + 参数 name:缓存名 + return 或者的值 """ return kcwcache.cache().get_cache(name) def del_cache(name): """删除缓存 + 参数 name:缓存名 + return Boolean类型 """ return kcwcache.cache().del_cache(name) def md5(strs): - """md5加密""" + """md5加密 + + 参数 strs:要加密的字符串 + + return String类型 + """ m = hashlib.md5() b = strs.encode(encoding='utf-8') m.update(b) return m.hexdigest() def times(): - """时间戳 精确到秒""" + """生成时间戳整数 精确到秒(10位数字) + + return int类型 + """ return int(time.time()) def json_decode(strs): """json字符串转python类型""" @@ -188,7 +218,7 @@ def json_decode(strs): except Exception: return {} def json_encode(strs): - """转成字符串""" + """python列表或字典转成字符串""" try: return json.dumps(strs,ensure_ascii=False) except Exception: @@ -290,22 +320,4 @@ def list_to_tree(data, pk = 'id', pid = 'pid', child = 'lowerlist', root=0,child if kkkk: v[child]=kkkk arr.append(v) - return arr -def get_url(url=''): - "获取版本下的url" - retstr='/' - HTTP_HOST=globals.HEADER.HTTP_HOST.split(".")[0] - route=config.route - modular=None - if route['modular']: - for mk in route['modular']: - if HTTP_HOST in mk: - modular=mk[HTTP_HOST] - if not modular: - retstr=retstr+globals.HEADER.PATH_INFO.split("/")[1]+"/" - if not route['edition']: - retstr=retstr+globals.HEADER.PATH_INFO.split("/")[2]+"/" - if not route['edition']: - retstr=retstr+globals.HEADER.PATH_INFO.split("/")[1]+"/" - retstr=retstr+url - return retstr \ No newline at end of file + return arr \ No newline at end of file diff --git a/common/request.py b/common/request.py index c2cbb4786364a99d95f442f47284930d0adbb7c9..3b2582af424886dde7fb415cb0372149ef0c1272 100644 --- a/common/request.py +++ b/common/request.py @@ -22,6 +22,17 @@ class froms: except: k=None return k +class HEADER: + def Method(): + return kcwglobals.HEADER.Method + def URL(): + return kcwglobals.HEADER.URL + def PATH_INFO(): + return kcwglobals.HEADER.PATH_INFO + def SERVER_PROTOCOL(): + return kcwglobals.HEADER.SERVER_PROTOCOL + def HTTP_HOST(): + return kcwglobals.HEADER.HTTP_HOST def get_data(): "获取请求参数体" return kcwglobals.HEADER.BODY_DATA diff --git a/config/__init__.py b/config/__init__.py index 776ce2fd710e3920cbcd49fd309ffd66784cbdde..554752af77a9ef8b0aee6586fbc202a7553e321e 100644 --- a/config/__init__.py +++ b/config/__init__.py @@ -88,7 +88,7 @@ email['recNick']='' #默认收件人昵称 kcweb={} kcweb['name']='kcweb' #项目的名称 -kcweb['version']='2.40.2' #项目版本 +kcweb['version']='2.40.7' #项目版本 kcweb['description']='基于python后端开发框架' #项目的简单描述 kcweb['long_description']='' #项目详细描述 kcweb['license']='MIT' #开源协议 mit开源 diff --git a/create.py b/create.py index 00686edf10392c76141f7e4d799e27bf4a72b8f8..036c0609b53146b54dd9fdf8f6e660720d95b0b6 100644 --- a/create.py +++ b/create.py @@ -23,6 +23,10 @@ class create: content=Template(self.path+"/application/common/__init__.py",appname=appname,modular=modular) f.write(content) f.close() + f=open(self.appname+"/common/autoload.py","w+",encoding='utf-8') + content=Template(self.path+"/application/common/autoload.py",appname=appname,modular=modular) + f.write(content) + f.close() if not os.path.exists(self.appname+"/config"): os.makedirs(self.appname+"/config") f=open(self.appname+"/config/__init__.py","w+",encoding='utf-8') @@ -56,6 +60,8 @@ class create: content=('# #gunicorn -b 0.0.0.0:39010 '+self.appname+':app\n'+ 'from kcweb import web\n'+ 'import '+self.appname+' as application\n'+ + 'from '+self.appname+'.common import *\n'+ + 'Queues.start() #开启队列监听\n'+ 'app=web(__name__,application)\n'+ 'if __name__ == "__main__":\n'+ ' #host监听ip port端口 name python解释器名字 (windows一般是python linux一般是python3)\n'+ diff --git a/utill/http.py b/utill/http.py index ad04124e5c3cca8d5e76ed2789715d33c3751fdd..7973038f168344cdb2e1f91c47509f082aa54227 100644 --- a/utill/http.py +++ b/utill/http.py @@ -13,12 +13,13 @@ class Http: set_encoding="utf-8" #设置text输出编码 set_session=True #是否启用会话 - get_header={} #响应头 - get_cookies={} #得到最后的响应cookie - get_text='' #得到body响应内容 - get_content='' #得到二进制内容 - get_response='' #得到响应对象 - get_status_code=None #响应状态码 + get_header={} #获取响应头 + get_cookies={} #获取最后的响应cookie + get_cookie_str='' #获取最后的响应cookie 字符串 + get_text='' #获取body响应内容 + get_content='' #获取body响应二进制内容 + get_response='' #获取响应对象 + get_status_code=None #获取响应状态码 req=None def gettext(self): @@ -53,6 +54,11 @@ class Http: self.get_cookies=cookie if self.set_cookies: self.get_cookies=self.__merge(self.set_cookies,self.get_cookies) + if self.get_cookies: + cookies='' + for key in self.get_cookies: + cookies=cookies+key+"="+self.get_cookies[key]+";" + self.get_cookie_str=cookies self.get_text=response.text self.get_content=response.content self.get_response=response diff --git a/utill/queues.py b/utill/queues.py new file mode 100644 index 0000000000000000000000000000000000000000..5dd9d709790cc306ef189e6dc6a8dc0f96a99be5 --- /dev/null +++ b/utill/queues.py @@ -0,0 +1,101 @@ +from queue import Queue +from .db import model +from .db import sqlite as kcwsqlite +import threading,time,os,hashlib,random +queuesdbpath=os.path.split(os.path.realpath(__file__))[0]+"/Queues" +class model_task(model.model): + "任务" + config={'type':'sqlite','db':queuesdbpath} + model.dbtype.conf=config + table="Queues" + fields={ + "id":model.dbtype.int(LEN=11,PRI=True,A_L=True), #设置id为自增主键 + "taskid":model.dbtype.varchar(LEN=32,DEFAULT=''), #设置id为自增主键 + "title":model.dbtype.varchar(LEN=1024,DEFAULT=''), #名称 + "describes":model.dbtype.varchar(LEN=2048,DEFAULT=''), #描述 + "code":model.dbtype.int(LEN=11,DEFAULT=2), #状态码 0成功 1失败 2等待中 3正在执行 4完成 + "msg":model.dbtype.text(), #状态描述 + "error":model.dbtype.text(), #异常信息 + "addtime":model.dbtype.int(LEN=11,DEFAULT=0) #添加时间 + } +class Queues(): + __globalqueue=None + def start(): + Queues.__globalqueue=Queue() + t=threading.Thread(target=Queues.__messagequeue) + t.daemon=True + t.start() + def __messagequeue(): + if not os.path.isfile(queuesdbpath): + t=model_task() + t.create_table() + kcwsqlite.sqlite().connect(queuesdbpath).table("Queues").where(True).delete() + while True: + if not Queues.__globalqueue.empty(): + value=Queues.__globalqueue.get() + kcwsqlite.sqlite().connect(queuesdbpath).table("Queues").where("taskid = '"+value['task']['taskid']+"' and code!=4").update({"code":3,"msg":"正在执行","error":""}) + if value['args']: + try: + value['target'](*value['args']) + except Exception as e: + kcwsqlite.sqlite().connect(queuesdbpath).table("Queues").where("taskid = '"+value['task']['taskid']+"' and code!=4").update({"code":1,"msg":"失败","error":str(e)}) + else: + kcwsqlite.sqlite().connect(queuesdbpath).table("Queues").where("taskid = '"+value['task']['taskid']+"' and code!=4").update({"code":4,"msg":"执行完成"}) + else: + try: + value['target']() + except Exception as e: + kcwsqlite.sqlite().connect(queuesdbpath).table("Queues").where("taskid = '"+value['task']['taskid']+"' and code!=4").update({"code":1,"msg":"失败","error":str(e)}) + else: + kcwsqlite.sqlite().connect(queuesdbpath).table("Queues").where("taskid = '"+value['task']['taskid']+"' and code!=4").update({"code":4,"msg":"执行完成"}) + else: + time.sleep(1) + def insert(target,args=None,title="默认任务",describes="",msg='等待中'): #add_queue + """添加队列 + + target 方法名 必须 + + args 方法参数 非必须 如 + + title 任务名称 + + describes 任务描述 + + return taskid + """ + if not os.path.isfile(queuesdbpath): + t=model_task() + t.create_table() + ttt=int(time.time()) + print(ttt) + m = hashlib.md5() + m.update((str(ttt)+str(random.randint(100000,999999))).encode(encoding='utf-8')) + taskid=m.hexdigest() + task={"taskid":taskid,"title":title,"describes":describes,"code":2,"msg":msg,"error":"","addtime":ttt} + key={"target":target,"args":args,"task":task} + Queues.__globalqueue.put(key) + kcwsqlite.sqlite().connect(queuesdbpath).table("Queues").insert(task) + return taskid + def getall(code=''): + """获取全部队列 + + code 1获取失败的任务 2获取等待中的任务 3获取正在执行中的任务 4获取执行完成的任务 + """ + if not os.path.isfile(queuesdbpath): + t=model_task() + t.create_table() + where=False + if code: + where="code="+code + # else: + # where="code!=4" + return kcwsqlite.sqlite().connect(queuesdbpath).table("Queues").field("taskid,title,describes,code,msg,error,addtime").where(where).select() + def status(taskid): + """获取任务状态 + + taskid 任务id + """ + if not os.path.isfile(queuesdbpath): + t=model_task() + t.create_table() + return kcwsqlite.sqlite().connect(queuesdbpath).table("Queues").field("taskid,title,describes,code,msg,error,addtime").where("taskid",taskid).find() \ No newline at end of file