Skip to main content

super kit box

Project description

skBox使用说明文档

目录

[TOC]

一、基本信息

版本 v0.26.2
作者 Hanmi Cheng
版本时间 2020.02.01
联系邮箱 jxmt089659@163.com

本包致力于为数据科学工作者提供一些辅助性的工具,其原点是数据分析、机器学习建模及其工程化过程中有许多反复造轮子的代码,基本面上许多其他开源工具已经提供了很好的支持,但总有一些使用不方便的问题。有许多的常见、常用函数也需要进行反复造轮子,代码其实非常容易如根据时间计算年龄之类的,所以本项目致力于以下几个方面:

  • 一些基本模块的简化封装以及底层问题的解决
  • 常用的计算逻辑,但又不耦合与业务的部分的封装
  • pandas dataframe及其周围衍生包的常用函数封装以及开发额外的功能

二、工具介绍

1. skBox.DfTool: pd.DataFrame工具

提供pandas的一些简化的代码操作封装

from skBox.DfTool import DataFrameDf

dfd = DataFrameDf(df=df)
# 重新获取df
df = dfd.df

1.1 数据列base64解码与编码

# 对指定列进行base64解码
dfd.base64_decoder(names=['col1', 'col2'])
# 对指定列进行base64编码
dfd.base64_encoder(names=['col1', 'col2'])

1.2 常规操作

dfd.drop(name=['col1', 'col2'])
dfd.rename(rename_dict={'改名前': '改名后'})

1.3 自动对列中的json格式数据进行递归拆解行转列

目前只做到对单列进行拆解。对于最后{k: v}格式数据 ,如果为list, 且list内数据不再包含另一个dict, 则数据不会进行继续拆分,防止数据从数据意义上做了没有必要的行转列。对于json格式内,一个dict内平级包含2个value为列表的数据,数据直接会计算笛卡尔积,可能造成错误,请尽量避免这种情况发生。如·'{"一年一班": [{"姓名": "张三"}, {"姓名": "李四"}],"一年二班":[{"姓名": "张三"}, {"姓名": "李四"}]}'

dfd.json_sep_entance(ex_col='RESP_MSG')

2. skBox.DocxApi:python写word文档

提供对python-docx的封装,利用python快速生产word文档(当然,内容得自己写)

from skBox.DocxApi import Docxer

doc = Docxer()

2.1 增加标题

doc.add_heading("我是谁")

2.2 增加段落

doc.add_paragraph("今天我去哪了", alignment='居中') # 目前只做了默认靠左和居中,其他还没写

2.3 根据pandas的df创建表格

df = pd.DataFrame({"aa": range(10), "bb":range(10, 20)}, index=range(-10, 0))
df.index.name = '我是索引'
doc.add_table(df, index=True)

2.4 插入图片

add_picture("e:/temp/test.jpg", width=6, height=None) # 目前支持单位 英尺(Inches)

3. 邮件发送模块

目前只支持腾讯企业邮箱,其他还没做,要做的话可能API会改. 目前代码结构还是有点问题的。

3.1. 一键使用方式

from skBox.MailTool import ExMail
mail = ExMail(user=user, passwd=passwd)
mail.send_email(self, to_list, cc_list, tag=None, body=None, doc=None, subtype=None):

4. skBox.skLogger:日志记录模块

skLogger为魔改封装版logging模块。提供一键默认配置,多进程日志打印,自定义日志格式,格式内自定义输出等功能。

4.1 线程安全的日志打印(功能最强)

from skBox.Toolbox import get_logger_prod, LoggerAdapter
# 快速初始化
logger = get_logger(log_file_name, level="info", log_dir=None, daily_handler=False, keep=1095, compress=True)

# 进阶用法,自定义Fomatter的参数,并且overwrite Logger类中的extra属性
logger = get_logger_prod('requestQualifier',
                         daily_handler=True,
                         level='debug',
                         log_fmt='%(asctime)s File \"%(filename)s\" [%(thread)d-%(reqId)s] %(levelname)s: %(message)s')
logger = LoggerAdapter(logger, extra={'reqId': 2333})
logger.info("我可以")

4.2 多进程下日志打印

4.2.1 多进程日志会有什么问题?

​ logging模块是线程安全的,但大多数python脚本都是cpu密集型运算。意味着在GIL机制下,python并不能有效利用多线程这种机制,需要开启多进程才能真正利用多核CPU。这一限制带来了许多问题,日志打印就是其中之一。

​ 以 TimedRotatingFileHandler 这个类的问题作为例子。这个Handler本来的作用是:按天切割日志文件。(当天的文件是xxxx.log 昨天的文件是xxxx.log.2016-06-01)。这样的好处是,一来可以按天来查找日志,二来可以让日志文件不至于非常大, 过期日志也可以按天删除。在每一个日志stream进行打印的时候logger会进行判断,是否需要rotation。以按天rotation为例子,如果Process-1在00:01收到一条日志记录请求,会判断当前时间是否满足routation条件,即logger类的rolloverAt属性所代表的时间,如果满足条件就会进行rotation,所以你会发现被rotated的日志文件的最后修改时间是在rolloverAt之后的第一条日志请求的时间点。

​ 阅读源码会发现,rotation的时候会先判断是否有目标文件,如果有则进行删除,然后重命名(没有rotater的情况下). 但是问题来了,如果是用多进程来输出日志,每个进程在何时收到日志请求并不确定。假设process1在00:00:01进行了rotation, process2在00:01:01进行了rotation。最终结果会是process2删除了前一天所有的日志,并且把process1创建的当前日志文件重命名为昨天的时间戳,其日志内容为 process1 在00:00:01-00:01:00之间打印的日志内容。

关于其他实现,参考 https://www.jianshu.com/p/d615bf01e37b,但本实现并没有完美解决多进程日志问题,在多个进程同时进行rotation的时候会因为文件被锁无法重命名导致一系列问题。文中提到的加文件锁的方法,确实暂时没有找到同时可以在Window,Linux平台下同时可以实现的办法,且实现复杂。

4.2.2 同一个主进程下多进程安全日志打印

总体思想是利用multiprocessing模块中的Queue进行进程间通讯,再利用一个独立的进程进行日志接受与打印工作,保证了日志的唯一性。功能同4.2类似

实现参考了官方logging文档进行了封装加工 https://docs.python.org/3/howto/logging-cookbook.html#logging-to-a-single-file-from-multiple-processes。

from skBox.skLogger import get_sender_logger, log_listener
import multiprocessing
import time

class LogTest(object):
    def __init__(self, ilogger, process_no):
        self.logger = ilogger
        self.process_no = process_no

    def run_test(self):
        for i in range(100):
            self.logger.info("count %s, process %s" % (i, self.process_no))
            time.sleep(0.5)


def work_starter(queue, no):
    logger = get_sender_logger(queue, "test_worker")
    LT = LogTest(ilogger=logger, process_no=no)
    LT.run_test()


if __name__ == '__main__':
    queue = multiprocessing.Queue()
    # 启动监听logger进程
    listener = multiprocessing.Process(target=log_listener,
                                       args=(queue, "test_listener"),
                                       kwargs={'log_dir': r'E:\code_work\skBox\temp\temp_log',                                                'daily_handler': True})
    listener.start()
    for i in range(3):
        p = multiprocessing.Process(target=work_starter, args=(queue, i, ))
        p.start()
4.2.3 多个独立进程下的多进程日志打印

multiprocessing的队列对于多个独立进程下的日志打印就束手无策了,针对这个问题,写了一个在此种情况下安全的日志打印功能。

但由于用的是直接寻找当前输出文件目录的办法,无法进行原来logging模块意义上的rotation和压缩,因为每个进程不会去判断是否应该rotation,而是直接去正确的文件打印日志(不关心其他进程在干嘛)。如果对于日志压缩有需求,目前想到的优化是,单独做一个定时日志压缩的服务来解决这个问题。且本模块,目前只支持俺天进行日志分割(本质上不会进行分割). 日志会被记录到log_dir/name_log.current_date文件下

from skBox.skLogger import get_save_daily_logger
logger = get_save_daily_logger(name, level='info', log_dir="/home/test/log", log_fmt=None)
logger.info("测试") # 在/home/test/log.{current_date} 文件下打印日志

4.3 小小的计时器?

目前是个玩具功能,一个简单的装饰器来记录类下函数的运行时间。

from skBox.skLogger import logger_time_it, get_logger_prod
import time

class Test(object):
    def __init__(self):
        self.logger = get_logger_prod("test_log")
        
    def my_test_func(self):
        time.sleep(20)

if __name__ == '__main__':  
    t = Test()
    t.my_test_func()

5. 杂项工具

一些常用的计算函数

from skBox.Toolbox import *

5.1 获得本机IP(内外网)

ip = get_host_ip(inner=True)

5.2 根据生日计算年龄

# born为出生日期,字符串 yyyyMMdd、yyyy-MM-dd、yyyy/MM/dd
# 默认用当前时间计算年龄,也可输入end_date=datetime.today(),支持同上的字符串以及datetime格式
# 小于1周年=0岁
age = calculate_age(born)

5.3 从二代身份证中抽取年龄和性别信息

首先会进行身份证合规性校验,如果不合规会返回None.

IE = IdnExtractor()
age = IE.extract_age(card_no)
gender = IE.extract_gender(card_no) # 1男,女

5.4 检查手机号合规性

如果合规返回手机号,不然返回空。可选在合规情况下返回运营商。目前可能会有覆盖不全的问题

PC = PhoneCheck()
phone = PC.check(phone)

5.5 根据时间起止与时间间隔创造时间列表

输入为字符串格式时间,开始和结束时间必须抱持格式一致。

date_list = create_assist_date(datestart=None, dateend=None,
                               infmt='%Y-%m-%d', ofmt='%Y-%m-%d',
                               unit='days', interval=1):

5.6 字符串全半角相互转换

res = strQ2B(ister) # 全角转半角
res = strB2Q(ister) # 半角转全角

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

skBox-0.26.2.tar.gz (20.8 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page