menu Chancel's Blog
rss_feed lightbulb_outline

我的笔记

Python3 - logging 以yaml形式配置项目日志

logging 支持YAML格式的日志配置文件,在项目入口main文件同一层添加logging.yaml文件,内容如下

version: 1
formatters:
  common:
    format: "%(asctime)s - %(levelname)s - %(threadName)s - %(message)s"
    datefmt: "%Y/%m/%d %H:%M:%S"
  console:
    format: "%(asctime)s - %(levelname)s - %(pathname)s - %(message)s"
    datefmt: "%Y/%m/%d %H:%M:%S"
handlers:
  # 不同会输出大于等于此级别的信息。
  common:
    class: logging.handlers.TimedRotatingFileHandler
    formatter: common
    level: INFO
    when: D
    interval: 1
    encoding: utf8
    filename: "logs/running.log"
    # suffix: "%Y-%m-%d.log"
    # 日志保留个数
    backupCount: 7
  console:
    class : logging.StreamHandler
    formatter: console
    level   : INFO
    stream  : ext://sys.stdout
loggers:
  main.common:
    level: INFO
    handlers: [common]
# 如果模块中没有使用 如logging.getLogger('main.common') 这样的配置来获取loggers中对应的配置,则默认会使用下面的root配置
root:
  level: DEBUG
  handlers: [console]

在main文件配置logging模块

import os
import yaml
import logging
import logging.config

os.chdir(os.path.abspath(os.path.dirname(os.path.abspath(__file__))))

# Logger config
if not os.path.exists('logs'):
    os.mkdir('logs')
# 日志配置
with open('logging.yaml', 'r', encoding='utf-8') as f:
    config = yaml.load(f, Loader=yaml.FullLoader)
    logging.config.dictConfig(config)
logger = logging.getLogger('main.common')

Develop Technology Python 2021-04-06 02:09:28 location_on

Python3 - 让脚本支持绝对路径启动

对于Python的写成YAML配置文件导入Logging模块应用来说,通常会导致在当前运行目录下生成logs文件夹

但我们运行项目通常是希望在项目目录下生成logs文件夹的,无论在哪一个目录启动Python项目,我们都更希望默认启动路径是项目的绝对路径

使用下面的代码放在入口方法处可以切换全局的Python项目启动路径为项目的绝对路径

import os

os.chdir(os.path.abspath(os.path.dirname(os.path.abspath(__file__))))

Develop Technology Python 2021-03-23 03:01:59 location_on

Python3 - Flask-Caching的过期时间设置(Flask缓存插件)

Flask-Caching是一个用于Flask框架的缓存插件,既支持高度的自定义继承开发,也支持简单的缓存存取,简单的缓存存取如下

from flask import Flask
from flask_caching import Cache

app = Flask(__name__)
app_cache = Cache(config={'CACHE_TYPE': 'filesystem', "CACHE_DEFAULT_TIMEOUT": 10, 'CACHE_DIR': '/tmp'})
app_cache.init_app(app)

@app.route("/")
def index():
    code = random.randint(0,9)
    if code is not None:
        cache.set("code", code)
    return render_templete_striing("<html><body>your code is {{code}}</body></html>")

@app.route("/login/<code>")
def login(code):
    cache_code = cache.get("code")
    if code == cache_code
        return render_templete_striing("<html><body>valid {{code}} !</body></html>")
    return render_templete_striing("<html><body>invalid {{code}} !</body></html>")

然而当我需要持久化缓存的时候,却发现Flask-Caching - 文档里对缓存过期参数 CACHE_DEFAULT_TIMEOUT 的描述只有

The default timeout that is used if no timeout is specified. Unit of time is seconds.

经过一番查找,在How can I configure Flask-Cache with infinite timeout -- stack overflow看到比较靠谱的答案

当使用 cache.set()的时候,如不传入timeout参数,则默认使用 CACHE_DEFAULT_TIMEOUT 参数的过期时间,如需持久化该缓存,则使用 timeout=0 即可

如下

from flask import Flask
from flask_caching import Cache

app = Flask(__name__)
app_cache = Cache(config={'CACHE_TYPE': 'filesystem', "CACHE_DEFAULT_TIMEOUT": 10, 'CACHE_DIR': '/tmp'})
app_cache.init_app(app)

cache.set("key", "value", timeout=0)

Develop Technology Python 2021-02-08 18:46:47 location_on

Python - 缓存字典到本地(支持多线程写入/读取)

缓存字典到本地(支持多线程写入/读取)

def GetIDTagDictByLocalTMP(id_tag: str):
    if ID_TAG_CACHE.get(id_tag):
        return ID_TAG_CACHE.get(id_tag)
    id_tag_dict = {'id': id_tag}
    SetIDTagDictToLocalTMP(id_tag, id_tag_dict)
    return id_tag_dict


def SetIDTagDictToLocalTMP(id_tag: str, id_tag_dict: dict):
    if not os.path.exists('tmp'):
        os.mkdir('tmp')
    ID_TAG_CACHE[id_tag] = id_tag_dict
    with open('cache/ID-TAG.json', 'w') as f:
        f.write(json.dumps(ID_TAG_CACHE, ensure_ascii=False))

def BuildIDTagCacheByLocalTmp():
    global ID_TAG_CACHE
    if not os.path.exists('cache'):
        os.mkdir('cache')
    if not os.path.exists('cache/ID-TAG.json'):
        return
    with open('cache/ID-TAG.json', 'r') as f:
        ID_TAG_CACHE = json.loads(f.read())

Develop Technology Python 2021-02-04 11:26:59 location_on

Python - 导出MySQL视图

import pymysql

'''
请按规则补充以下信息,并运行该脚本,即可获取按顺序导出的视图
    HOST:数据库IP地址
    PORT:数据库端口
    USER:用户名称
    PASSWD:用户密码
    DB_NAME:数据库名称
    CHARSET:编码格式(中文可默认 utf8mb4 )
'''

HOST = '192.168.11.214'
PORT = 3306
USER = 'root'
PASSWD = 'my_passwd'
DB_NAME = 'syncthing_manage'
CHARSET = 'utf8mb4'


conn = pymysql.connect(host=HOST, port=PORT, user=USER,
                       passwd=PASSWD, db=DB_NAME, charset=CHARSET)


def process_rely(parmas={}, rely_old=[]):
    _rely = []
    _keys = list(parmas.keys())
    for k in rely_old:
        for bl in _keys:
            if str(parmas[k]).find(bl) > -1:
                if bl not in _rely:
                    if k not in _rely:
                        _rely.append(bl)
                    else:
                        i = _rely.index(k)
                        _rely.insert(i, bl)
                else:
                    if k in _rely:
                        i = _rely.index(k)
                        j = _rely.index(bl)
                        if i < j:
                            del _rely[j]
                            _rely.insert(i, bl)
        if k not in _rely:
            _rely.append(k)
    return _rely


cur = conn.cursor()
cur.execute('select TABLE_NAME, VIEW_DEFINITION from  information_schema.VIEWS where TABLE_SCHEMA = %s ', DB_NAME)
rs = cur.fetchall()
cur.close()
conn.close()

ps = {}
for al in rs:
    ps['`' + al[0] + '`'] = al[1]

rely = process_rely(ps, list(ps.keys()))
# rely = process_rely(ps, rely1)

file_object = open('view.sql', 'w')
for al in rely:
    file_object.write('DROP VIEW IF EXISTS ' + al + ';\n')
    file_object.write('CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`%` SQL SECURITY DEFINER VIEW ' + al +
                      ' AS ' + ps[al] + ';\n\n')

file_object.close()

Develop Technology Python 2021-03-20 15:51:35 location_on

Python - 登录二次验证实现

Python二次登录验证的实现,依赖于pyotp包

import pyotp

sec = pyotp.random_base32()
totp = pyotp.totp.TOTP(sec,interval=60)
qr_code_text = totp.provisioning_uri(name='Chancel.Yang', issuer_name='Secure App')
print('登录二次验证器创建成功,二维码数据->%s' % qr_code_text)

# 可选:生成验证码步骤
import qrcode
img = qrcode.make(qr_uri)
img.get_image().show()

```

Develop Technology Python 2021-02-04 11:19:20 location_on

Python - 命令行参数解析

命令行参数有两种

# 参数一
python3 main.py agrs1 agrs2 agrs3
# 参数二
python3 main.py -a aaa -b bbb

参数一的识别获取

import sys

print('输出的参数个数为:%d个参数' % len(sys.argv))
print('输出参数列表%s' % str(sys.argv))

调用输出如下

❯ python3 test.py a b c                                                    
输出的参数个数为:4个参数
输出参数列表['test.py', 'a', 'b', 'c']


参数二的识别获取

import argparse

parser = argpaimport argparse
rse.ArgumentParser(description='Test for argparse')
parser.add_argument('--port', '-p', help='端口参数', default='8220')
parser.add_argument('--config', '-c', help='配置文件路径', default='config.ini')
args = parser.parse_args()

print('port参数:%s,config参数:%s' % (args.port,agrs.config))

调用输出如下

❯ python3 test.py -p 20931 -c /home/apps/fuck                              
port参数:20931,config参数:/home/apps/fuck

Develop Technology Python 2021-02-01 17:17:10 location_on

Python3 - python-markdown2 代码颜色渲染

python-markdown2是Python一个将Markdown文本翻译成HTML文档的第三方库,仓库传送门:trentm/python-markdown2

Markdown is a light text markup format and a processor to convert that to HTML.

访问文档的扩展插件部分说明页面(Extras provided by markdown2.py

可以看code-color扩展插件部分,按照作者的说法,这部分已经在1.3.0版本之后废弃不用了,改用 fenced-code-blocks扩展插件

使用扩展插件方法,只需要在执行转换的方法时候添加扩展插件参数

import markdown2

markdown_extras = ['fenced-code-blocks']
html_content = markdown2.markdown(article_content.a_content, extras=g.markdown_extras)

可以看到生成的 html_content文档的div节点class属性是codehilite,其子元素的class也标记上了

最后一步我们只需要引入pygments-css的CSS文件,将引入的CSS文件class类名从highlight 修改成 codehilite,就可以将代码颜色渲染了

Develop Technology Python 2021-01-20 15:23:42 location_on

Python3 - 复制文件到别的文件夹下

Python3复制文件

import os
import shutil

def copy_file(src_file_path:str,target_file_path:str):
    if not os.path.isfile(src_file_path):
        return False
    file_path=os.path.split(target_file_path)[0]
    if not os.path.exists(file_path):
        os.makedirs(file_path)            
    shutil.copyfile(src_file_path,target_file_path)  

if __name__ == '__main__':
    copy_file('C:\\A\\fuck.txt','c:\\B\\fuck.txt')

Develop Technology Python 2021-01-18 14:56:14 location_on

Python3 - 递归获取目录下的所有文件(含子目录内文件)

Python3递归获取目录下的所有文件(含子目录内文件)

测试版本:Python3.6.9

import os

def get_list_by_folder(path):
    list_name = []
    for file in os.listdir(path):
        file_path = os.path.join(path, file)
        if not os.path.isdir(file_path):
            list_name.append(file_path)
        else:
            list_name.extend(GetListByFolder(file_path))
    return list_name

if __name__=='__main__':
    file_list = get_list_by_folder("./")
    print(file_list)

Develop Technology Python 2021-01-18 14:48:07 location_on

1 of 2 | A total of 16