Python导入包顺序
标准库导入
相关第三方库导入
本地应用/库的导入,按照字母顺序
配置pip源 Linux系统 执行命令即可
pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
Windows系统
在C:\Users\Administrator下新建pip文件夹
在文件夹里新建pip.ini文件,并写入如下内容
[global] index-url = https://pypi.tuna.tsinghua.edu.cn/simple/ [install] trusted-host = pypi.tuna.tsinghua.edu.cn
*args与*kwargs 的区别 *args 用于传递可变数量的非关键字参数,以元组 的形式传递。
*kwargs 用于传递可变数量的关键字参数,以字典 的形式传递。
def example_function (*args, **kwargs ): print ("Non-keyword arguments:" ) for arg in args: print (arg) print ("\nKeyword arguments:" ) for key, value in kwargs.items(): print (f"{key} : {value} " ) example_function("apple" , "banana" , "cherry" , fruit1="orange" , fruit2="kiwi" )
装饰器 装饰器是Python的一个特性,可以让我们在不修改原函数的情况下,动态增加函数的功能。
其本质上装饰器是一个函数,它接收一个函数的输入,返回一个新函数的输出。
装饰器的使用 def my_wrapper (func ): """ Dao层的捕获错误装饰器 :param func: :return: """ def wrapper (*args, **kwargs ): try : res = func(*args, **kwargs) print ("this is wrapper" , res) return res + 1 except Exception as err: print ("exceptions_wrapper_dao" , err) raise err return wrapper @my_wrapper def test (): a = 1 + 2 return a if __name__ == '__main__' : r = test() print (r)
通过打断点可以知道:执行test函数时,会跳转到wrapper函数里,执行func函数时,会执行test函数里的内容,最后return的结果作为执行test函数的结果。
装饰器的参数 也就是在原有的基础上套上一层函数
def my_wrapper (n ): """ Dao层的捕获错误装饰器 """ def decorator (func ): def wrapper (*args, **kwargs ): try : res = func(*args, **kwargs) print ("this is wrapper" , res) print ("this is n ->>" , n) return res + 1 except Exception as err: print ("exceptions_wrapper_dao" , err) raise err return wrapper return decorator @my_wrapper(123 ) def test (): a = 1 + 2 return a if __name__ == '__main__' : r = test() print (r)
logging日志重复输出 logging封装代码
import loggingimport timefrom io import StringIOimport osfrom config import LOG_FILE_DIRclass MyLogger : def __init__ (self, name=None ): if name is None : name = __name__ log_path = os.path.join(LOG_FILE_DIR, time.strftime('%Y-%m-%d %H%M%S' , time.localtime(time.time())) + ".log" ) if not os.path.exists(LOG_FILE_DIR): os.makedirs(LOG_FILE_DIR) self.logger = logging.getLogger(name) self.logger.setLevel(logging.DEBUG) self.log_string = StringIO() self.log_string_global = StringIO() file_handler = logging.FileHandler(log_path) file_handler.setLevel(logging.DEBUG) console_handler = logging.StreamHandler() console_handler.setLevel(logging.DEBUG) string_handler = logging.StreamHandler(self.log_string) string_handler.setLevel(logging.DEBUG) string_global_handler = logging.StreamHandler(self.log_string_global) string_global_handler.setLevel(logging.DEBUG) formatter = logging.Formatter( fmt="%(asctime)s %(name)s %(filename)s %(funcName)s %(lineno)d %(message)s" , datefmt="%Y-%m-%d %X" ) file_handler.setFormatter(formatter) console_handler.setFormatter(formatter) string_handler.setFormatter(formatter) string_global_handler.setFormatter(formatter) self.logger.handlers.clear() self.logger.addHandler(file_handler) self.logger.addHandler(console_handler) self.logger.addHandler(string_handler) self.logger.addHandler(string_global_handler) def print_log (self, msg, level='info' ): if level == 'debug' : self.logger.debug(msg) elif level == 'info' : self.logger.info(msg) elif level == 'warning' : self.logger.warning(msg) elif level == 'error' : self.logger.error(msg) elif level == 'critical' : self.logger.critical(msg) log_contents = self.log_string.getvalue() self.log_string.truncate(0 ) self.log_string.seek(0 ) return log_contents def get_global_log (self ): """ 获取全局日志信息 :return: """ return self.log_string_global.getvalue() def clear_global_log (self ): """ 清除全局日志信息 :return: """ self.log_string_global.truncate(0 ) self.log_string_global.seek(0 )
不同的name对应不同的logger。同样的logger,它们会共享handler,从而导致日志重复输出。
解决方法:
提供不同的name值
在添加处理器时,清除处理器
线程锁 涉及多线程使用同一类时,可以为该类添加线程锁,当前线程在用着时,其他线程就不能使用
场景:启动flask时,会使用日志输出flask启动信息,而启动发送邮件线程也会使用日志输出启动信息,因为log的特殊性,输出当前信息就得清空log,所以两个线程同时使用的时候,后者线程可能刚输出日志之后就会被前者线程清空log。
解决方法:为日志类添加线程锁
class MyLoggerInfo (MyLogger ): text_browser = None lock = threading.Lock() def __init__ (self ): super ().__init__() @staticmethod def set_text_browser (text_browser ): """ 设置日志信息框 :param text_browser: :return: """ MyLoggerInfo.text_browser = text_browser def print_log (self, msg, level='info' , is_print_to_text=True ): """ 输出日志 :param msg: 日志信息 :param level: 日志等级 :param is_print_to_text: 是否输出到qt信息框中 :return: """ with self.lock: text_log = super ().print_log(msg, level) if is_print_to_text: if MyLoggerInfo.text_browser is not None : MyLoggerInfo.text_browser.append(text_log
解决错误码 -1073741819 (0xC0000005) 执行到某行代码时,程序自动停止,出现错误Process finished with exit code -1073741819 (0xC0000005)
出现原因 :与金山词霸、有道词典等软件的划词功能有关
可能是因为这些软件和程序使用相同的系统资源
可视化打包Python程序 执行安装命令,pip install auto-py-to-exe
执行打包程序打开命令,auto-py-to-exe
解决问题 AssertionError AssertionError: View function mapping is overwriting an existing endpoint function: message.w
问题原因:flask路由使用了相同的endpoint函数
解决方法:
方法一 重命名装饰器的名字
def flask_controller_info (req ): """ 装饰器 :param req: 请求该接口的参数 :return: """ def f (func ): def w (*args, **kwargs ): res = func(*args, **kwargs) return res w.__name__ = func.__name__ return w return f
方法二 可以设置@app.route的endpoint名,以避免出现重名的endpoint函数
@app.route("/path1" , endpoint='func1' ) @exception_handler def func1 (): pass @app.route("/path2" , endpoint='func2' ) @exception_handler def func2 (): pass
pipwin pipwin是一个Python包管理器,它会自动安装来自http://www.lfd.uci.edu/~gohlke/pythonlibs/的包,非常方便。如果遇到pip找不到,或者说pip下载启动wheel编译后却失败的情况,不妨尝试一下这个工具。
pipwin的主要作用是解决pip在Windows系统中的一些兼容性问题,比如安装某些Python包时需要编译C++代码或者需要一些特定的编译器等。
注:http://www.lfd.uci.edu/~gohlke/pythonlibs/ 是一个提供Python库下载的网站,它提供了许多科学开源扩展包的32位和64位Windows二进制文件,这些包是官方CPython发行版所需的。
生成requirements文件 整个环境下的安装包都保存到requirements.txt中
弃用 pip freeze > requirements.txt pip list --format=freeze > requirements.txt
只生成单个项目中的使用到的安装包
pip install pipreqs pipreqs .
执行安装requirements.txt
pip install -r requirements.txt
filter方法 接收两个参数,函数、列表
函数计算得到为True的元素返回到新的列表中
def is_even (num ): return num % 2 == 0 numbers = [1 , 2 , 3 , 4 , 5 , 6 ] even_numbers = list (filter (is_even, numbers)) print (even_numbers)
request 在使用request的get方法时,params参数只支持一层的dict自动转换成url编码,因此如果有多层的dict需要将第二层以上的转为字符串
parmas = { "a" : { "a-1" : 1 , "a-2" : 2 }, "b" : { "b-1" : 1 } } parmas = { "a" : json.dumps({ "a-1" : 1 , "a-2" : 2 }), "b" : json.dumps({ "b-1" : 1 }) }
数学计算 保留n位小数 def reserve_significant_digits (num, n=6 ): """ 保留n位有效数字 @return: """ significant = f'%.{n} g' return significant % num
matplotlib库添加字体 python import matplotlibmatplotlib.matplotlib_fname()
输出matplotlib的字体库位置,/usr/local/lib/python3.11/site-packages/matplotlib/mpl-data/matplotlibrc
将tff格式的字体复制到/usr/local/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf中
mv xxx.ttf /usr/local/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/xxx.ttf
清空缓存
python import matplotlibmatplotlib.get_cachedir() rm -rf 地址
查看字体是否添加
python from matplotlib import font_managerfor font_name in sorted (font_manager.get_font_names()): print (font_name)
alembic ORM数据库使用 库安装
配置连接池 main_engine = None main_session = None MainBase = None def connect_main_mysql (): """ 连接数据库 """ global main_engine, main_session, MainBase print ("------------------" ) print (Config.DB_URI) print ("---------------------" ) main_engine = create_engine(Config.DB_URI) main_session = Session(bind=main_engine) MainBase = declarative_base() connect_main_mysql()
初始化配置
执行该命令会在项目根目录下新建一个alembic.ini文件和alembic文件夹
修改配置 打开alembic.ini文件,配置连接池
sqlalchemy.url = sqlite:///module.sqlite
打开alembic/env.py文件,配置迁移的模型
... from apps.models.SYS_Model import * from db_exts import MainBase target_metadata = MainBase.metadata ...
生成迁移文件 alembic revision --autogenerate -m "Initial migration"
执行迁移
回滚命令