Commit e08c69f0 authored by 纪超's avatar 纪超

完成日志、配置文件、数据库工具模块

parent 1cdf15b9
......@@ -4,6 +4,3 @@
*.zip
*.log
/venv/
/logs/log/
/utils/log/
/strategy/resource/
database:
host: ${MYSQL_HOST:127.0.0.1}
port: ${MYSQL_PORT:3306}
user: ${MYSQL_USER:root}
password: ${MYSQL_PWD:123456}
dbname: ${MYSQL_DBNAME:robo_pmpt}
email:
server: smtphz.qiye.163.com
user: jft-ra@thizgroup.com
password: 5dbb#30ec6d3
logger:
version: 1
formatters:
brief:
format: "%(asctime)s - %(levelname)s - %(message)s"
simple:
format: "%(asctime)s - %(filename)s - %(levelname)s - %(message)s"
handlers:
console:
class: logging.StreamHandler
formatter: simple
level: INFO
stream: ext://sys.stdout
file:
class: logging.handlers.TimedRotatingFileHandler
level: INFO
formatter: brief
filename: logs/info.log
interval: 1
backupCount: 30
encoding: utf8
when: D
loggers:
base:
handlers: [console,file]
level: INFO
propagate: 0
root:
level: INFO
handlers: [console,file]
# email:
# host: smtphz.qiye.163.com
# port: 25
# from: jft-ra@thizgroup.com
# pw: 5dbb#30ec6d3
# tos: chao.zheng@thizgroup.com
# subject: test
# This is a sample Python script.
from utils import *
import utils as ut
# Press ⌃R to execute it or replace it with your code.
# Press Double ⇧ to search everywhere for classes, files, tool windows, actions, and settings.
def print_hi(name):
# Use a breakpoint in the code line below to debug your script.
print(f'Hi, {name}') # Press ⌘F8 to toggle the breakpoint.
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
print_hi('PyCharm')
# See PyCharm help at https://www.jetbrains.com/help/pycharm/
print(dir())
print(dir(ut))
import re
from functools import partial
from .base import *
import yaml
has_regex_module = False
ENV_VAR_MATCHER = re.compile(
r"""
\$\{ # match characters `${` literally
([^}:\s]+) # 1st group: matches any character except `}` or `:`
:? # matches the literal `:` character zero or one times
([^}]+)? # 2nd group: matches any character except `}`
\} # match character `}` literally
""", re.VERBOSE
)
IMPLICIT_ENV_VAR_MATCHER = re.compile(
r"""
.* # matches any number of any characters
\$\{.*\} # matches any number of any characters
# between `${` and `}` literally
.* # matches any number of any characters
""", re.VERBOSE
)
RECURSIVE_ENV_VAR_MATCHER = re.compile(
r"""
\$\{ # match characters `${` literally
([^}]+)? # matches any character except `}`
\} # match character `}` literally
([^$}]+)? # matches any character except `}` or `$`
\} # match character `}` literally
""",
re.VERBOSE,
)
def _replace_env_var(match):
env_var, default = match.groups()
value = os.environ.get(env_var, None)
if value is None:
# expand default using other vars
if default is None:
# regex module return None instead of
# '' if engine didn't entered default capture group
default = ''
value = default
while IMPLICIT_ENV_VAR_MATCHER.match(value): # pragma: no cover
value = ENV_VAR_MATCHER.sub(_replace_env_var, value)
return value
def env_var_constructor(loader, node, raw=False):
raw_value = loader.construct_scalar(node)
# detect and error on recursive environment variables
if not has_regex_module and RECURSIVE_ENV_VAR_MATCHER.match(
raw_value
): # pragma: no cover
raise Exception(
"Nested environment variable lookup requires the `regex` module"
)
value = ENV_VAR_MATCHER.sub(_replace_env_var, raw_value)
if value == raw_value:
return value # avoid recursion
return value if raw else yaml.safe_load(value)
def _setup_yaml_parser():
yaml.add_constructor('!env_var', env_var_constructor, yaml.SafeLoader)
yaml.add_constructor(
'!raw_env_var',
partial(env_var_constructor, raw=True),
yaml.SafeLoader
)
yaml.add_implicit_resolver(
'!env_var', IMPLICIT_ENV_VAR_MATCHER, Loader=yaml.SafeLoader
)
def _get_config(config_name=None):
CONFIG_NAME = config_name or 'config.yml'
path = f'{get_project_path()}{os.path.sep}config.yml'
with open(path, 'r', encoding='utf-8') as f:
return yaml.safe_load(f)
if __name__ == '__main__':
_get_config()
from .date import *
from .base import *
from .__env_config import _setup_yaml_parser, _get_config
from .__logger import _setup_logger
_setup_yaml_parser()
config = _get_config()
if 'logger' in config:
logger = _setup_logger(config['logger'])
from logging import config as cf, getLogger
from .base import *
def _setup_logger(config, name='base'):
if 'handlers' in config and 'file' in config['handlers']:
file = config['handlers']['file']
path = os.path.join(get_project_path(), file["filename"])
os.makedirs(os.path.split(path)[0], exist_ok=True)
file["filename"] = os.path.abspath(path)
cf.dictConfig(config)
return getLogger(name)
import os
def get_project_path():
for anchor in ['.idea', '.git', 'config.yml', 'requirements.txt']:
path = os.path.realpath(os.curdir)
while anchor not in os.listdir(path):
parent = os.path.dirname(path)
if parent == path:
path = None
break
else:
path = parent
if path is not None:
return path
return None
def deep_dict_update(d1, d2):
for key in d1:
if key not in d2:
continue
if isinstance(d1[key], dict) and isinstance(d2[key], dict):
deep_dict_update(d1[key], d2[key])
else:
d1[key] = d2[key]
for key in d2:
if key not in d1:
d1[key] = d2[key]
if __name__ == '__main__':
print(get_project_path())
# print(os.path.dirname('/123123/123123'))
import calendar
from datetime import timedelta
def filter_weekend(day):
while calendar.weekday(day.year, day.month, day.day) in [5, 6]:
day = day - timedelta(1)
return day
def next_workday(day):
result = day
while result == day or result.weekday() in [5, 6]:
result = result + timedelta(1)
return result
def is_workday(day):
return day.weekday() in range(5)
import functools
import pymysql
import threading
from pymysql.cursors import DictCursor
from utils import config
class Database:
def __init__(self, conf=None):
self.config = conf or config['database']
def __enter__(self):
port = 3306
if 'port' in self.config.keys():
port = self.config['port']
self.__connect = pymysql.connect(host=self.config['host'], user=self.config['user'], port=port,
password=str(self.config['password']), database=self.config['dbname'])
self.__cursor = self.connect.cursor(DictCursor)
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.cursor.close()
self.connect.close()
@property
def connect(self):
return self.__connect
@property
def cursor(self):
return self.__cursor
__local__ = threading.local()
def read(func=None, one=False):
if func is None:
return functools.partial(read, one=one)
def execute(db, sql):
db.cursor.execute(sql)
result = db.cursor.fetchall()
if one:
return result[0] if result else None
else:
return result
@functools.wraps(func)
def wraps(*args, **kwargs):
sql = func(*args, **kwargs)
if hasattr(__local__, 'db'):
return execute(__local__.db, sql)
else:
with Database() as db:
return execute(db, sql)
return wraps
def write(func=None):
if func is None:
return functools.partial(func)
def execute(db, sqls):
if isinstance(sqls, list):
for sql in sqls:
db.cursor.execute(sql)
else:
db.cursor.execute(sqls)
@functools.wraps(func)
def wraps(*args, **kwargs):
sqls = func(*args, **kwargs)
if hasattr(__local__, 'db'):
execute(__local__.db, sqls)
else:
with Database() as db:
try:
execute(db, sqls)
db.connect.commit()
except Exception as e:
db.connect.rollback()
raise e
return wraps
def transaction(func=None):
if func is None:
return functools.partial(func)
@functools.wraps(func)
def wraps(*args, **kwargs):
if hasattr(__local__, 'db'):
return func(*args, **kwargs)
with Database() as db:
__local__.db = db
try:
result = func(*args, **kwargs)
db.connect.commit()
return result
except Exception as e:
db.connect.rollback()
raise e
return wraps
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment