<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Python on kutake小站</title><link>https://www.kutake.top/categories/python/</link><description>Recent content in Python on kutake小站</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Sat, 10 Feb 2024 16:15:40 +0800</lastBuildDate><atom:link href="https://www.kutake.top/categories/python/index.xml" rel="self" type="application/rss+xml"/><item><title>在有共同字段下的pydantic类转换不正确问题</title><link>https://www.kutake.top/archives/%E5%9C%A8%E6%9C%89%E5%85%B1%E5%90%8C%E5%AD%97%E6%AE%B5%E4%B8%8B%E7%9A%84pydantic%E7%B1%BB%E8%BD%AC%E6%8D%A2%E4%B8%8D%E6%AD%A3%E7%A1%AE%E9%97%AE%E9%A2%98/</link><pubDate>Sat, 10 Feb 2024 16:15:40 +0800</pubDate><guid>https://www.kutake.top/archives/%E5%9C%A8%E6%9C%89%E5%85%B1%E5%90%8C%E5%AD%97%E6%AE%B5%E4%B8%8B%E7%9A%84pydantic%E7%B1%BB%E8%BD%AC%E6%8D%A2%E4%B8%8D%E6%AD%A3%E7%A1%AE%E9%97%AE%E9%A2%98/</guid><description>&lt;p&gt;在使用 Pydantic 进行数据验证和设置时，你可能会遇到一个问题：当多个类有共同字段时，Pydantic 可能无法正确地区分这些类。让我通过一个简单的例子来解释这个问题。&lt;/p&gt;</description></item><item><title>基于Route来解决playwright的静态HTML资源加载问题</title><link>https://www.kutake.top/archives/%E5%9F%BA%E4%BA%8Eroute%E6%9D%A5%E8%A7%A3%E5%86%B3playwright%E7%9A%84%E9%9D%99%E6%80%81html%E8%B5%84%E6%BA%90%E5%8A%A0%E8%BD%BD%E9%97%AE%E9%A2%98/</link><pubDate>Sat, 10 Feb 2024 16:14:14 +0800</pubDate><guid>https://www.kutake.top/archives/%E5%9F%BA%E4%BA%8Eroute%E6%9D%A5%E8%A7%A3%E5%86%B3playwright%E7%9A%84%E9%9D%99%E6%80%81html%E8%B5%84%E6%BA%90%E5%8A%A0%E8%BD%BD%E9%97%AE%E9%A2%98/</guid><description>&lt;h2 id="前因"&gt;前因&lt;/h2&gt;
&lt;p&gt;由于python中没有方便快捷生成美观图片的方案，所以我使用了jinja2模板生成html后交给playwright生成网页图片，这其中，图片资源可以使用base64格式解决，而字体加载就难了。&lt;/p&gt;</description></item><item><title>从创建项目到测试打包上传Pypi</title><link>https://www.kutake.top/archives/%E4%BB%8E%E5%88%9B%E5%BB%BA%E9%A1%B9%E7%9B%AE%E5%88%B0%E6%B5%8B%E8%AF%95%E6%89%93%E5%8C%85%E4%B8%8A%E4%BC%A0pypi/</link><pubDate>Mon, 30 Oct 2023 20:16:30 +0800</pubDate><guid>https://www.kutake.top/archives/%E4%BB%8E%E5%88%9B%E5%BB%BA%E9%A1%B9%E7%9B%AE%E5%88%B0%E6%B5%8B%E8%AF%95%E6%89%93%E5%8C%85%E4%B8%8A%E4%BC%A0pypi/</guid><description>&lt;h2 id="前言"&gt;前言&lt;/h2&gt;
&lt;p&gt;这是一次从创建项目到测试打包上传Pypi的过程，记录一下。&lt;/p&gt;
&lt;h2 id="创建项目"&gt;创建项目&lt;/h2&gt;
&lt;p&gt;这里我是用的是&lt;code&gt;pdm&lt;/code&gt;这个包管理工具，创建项目的命令是&lt;code&gt;pdm init&lt;/code&gt;，跟着引导一步步走，之后会生成一个&lt;code&gt;pyproject.toml&lt;/code&gt;文件，里面有项目的一些基本信息，比如作者、版本号等。下面是一个示例：&lt;/p&gt;</description></item><item><title>更优雅的包可用性检测</title><link>https://www.kutake.top/archives/%E6%9B%B4%E4%BC%98%E9%9B%85%E7%9A%84%E5%8C%85%E5%8F%AF%E7%94%A8%E6%80%A7%E6%A3%80%E6%B5%8B/</link><pubDate>Sun, 06 Aug 2023 03:32:54 +0800</pubDate><guid>https://www.kutake.top/archives/%E6%9B%B4%E4%BC%98%E9%9B%85%E7%9A%84%E5%8C%85%E5%8F%AF%E7%94%A8%E6%80%A7%E6%A3%80%E6%B5%8B/</guid><description>&lt;h2 id="一般"&gt;一般&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;ImportError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;numpy is not installed&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="更推荐"&gt;更推荐&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;importlib.util&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;find_spec&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;find_spec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;numpy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;numpy is installed&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;numpy is not installed&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Rich 使用PY在终端上展示富文本界面</title><link>https://www.kutake.top/archives/rich-%E4%BD%BF%E7%94%A8py%E5%9C%A8%E7%BB%88%E7%AB%AF%E4%B8%8A%E5%B1%95%E7%A4%BA%E5%AF%8C%E6%96%87%E6%9C%AC%E7%95%8C%E9%9D%A2/</link><pubDate>Fri, 28 Jul 2023 02:15:54 +0800</pubDate><guid>https://www.kutake.top/archives/rich-%E4%BD%BF%E7%94%A8py%E5%9C%A8%E7%BB%88%E7%AB%AF%E4%B8%8A%E5%B1%95%E7%A4%BA%E5%AF%8C%E6%96%87%E6%9C%AC%E7%95%8C%E9%9D%A2/</guid><description>&lt;h2 id="安装"&gt;安装&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;rich&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# PDM&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pdm&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="n"&gt;rich&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://rich.readthedocs.io/en/latest/introduction.html"&gt;文档&lt;/a&gt; &amp;amp; &lt;a href="https://github.com/Textualize/rich"&gt;源码&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="基础"&gt;基础&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rich&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Hello World&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Rich功能非常丰富，从日志处理到富文本显示甚至动态的终端界面。&lt;/p&gt;
&lt;p&gt;要使用Rich用做界面的话，一般是这样的：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rich.console&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rich.layout&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Layout&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rich.panel&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;console&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;panel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Panel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;panel_name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;layout_name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;界面&lt;code&gt;Layout&lt;/code&gt;和面板&lt;code&gt;Panel&lt;/code&gt;是经常要用到的东西，&lt;code&gt;Layout&lt;/code&gt;作为界面布局，&lt;code&gt;Panel&lt;/code&gt;内展示元素并风格化，比如经常使用的表格&lt;code&gt;Table&lt;/code&gt;；要实现动态变化而不是print需要用到&lt;code&gt;Live&lt;/code&gt;。&lt;/p&gt;</description></item><item><title>一个PY多数据源的统一入口思路</title><link>https://www.kutake.top/archives/%E4%B8%80%E4%B8%AApy%E5%A4%9A%E6%95%B0%E6%8D%AE%E6%BA%90%E7%9A%84%E7%BB%9F%E4%B8%80%E5%85%A5%E5%8F%A3%E6%80%9D%E8%B7%AF/</link><pubDate>Fri, 21 Apr 2023 22:41:27 +0800</pubDate><guid>https://www.kutake.top/archives/%E4%B8%80%E4%B8%AApy%E5%A4%9A%E6%95%B0%E6%8D%AE%E6%BA%90%E7%9A%84%E7%BB%9F%E4%B8%80%E5%85%A5%E5%8F%A3%E6%80%9D%E8%B7%AF/</guid><description>&lt;h2 id="需求"&gt;需求&lt;/h2&gt;
&lt;p&gt;以我的bot来说：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Bot:
├─config
├─core
├─modules
│ ├─required
│ │ ├─BotManager
│ │ ├─BotStatus
│ │ ├─ExceptionCatch
│ │ ├─...
│ └─self
│ ├─Modules1
│ ├─Modules2
│ ├─...
├─resources
├─service
└─utils
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;模块统一放在&lt;code&gt;modules&lt;/code&gt;下，&lt;code&gt;required&lt;/code&gt;是bot运行必须的模块，&lt;code&gt;self&lt;/code&gt;是可卸载安装的模块。&lt;/p&gt;</description></item><item><title>sqlalchemy&amp;sqlmodel的commit后数据丢失问题</title><link>https://www.kutake.top/archives/sqlalchemysqlmodel%E7%9A%84commit%E5%90%8E%E6%95%B0%E6%8D%AE%E4%B8%A2%E5%A4%B1%E9%97%AE%E9%A2%98/</link><pubDate>Sat, 11 Mar 2023 01:50:07 +0800</pubDate><guid>https://www.kutake.top/archives/sqlalchemysqlmodel%E7%9A%84commit%E5%90%8E%E6%95%B0%E6%8D%AE%E4%B8%A2%E5%A4%B1%E9%97%AE%E9%A2%98/</guid><description>&lt;h2 id="描述"&gt;描述&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# name=user,age=18, ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# empty&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="原因"&gt;原因&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;sqlalchemy&lt;/code&gt;为了保持&lt;code&gt;session&lt;/code&gt;内的数据同步，默认了&lt;code&gt;expire_on_commit&lt;/code&gt;为&lt;code&gt;True&lt;/code&gt;，它表现在：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 查询&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 更改数据&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;user_b&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# commit后再次访问，其实是重新进行了select操作&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# user_b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;expire_on_commit&lt;/code&gt;可以用来更改 SQLAlchemy 的对象刷新机制，默认值为&lt;code&gt;True&lt;/code&gt;即在&lt;code&gt;session&lt;/code&gt;调用&lt;code&gt;commit&lt;/code&gt;之后会主动将同一个&lt;code&gt;session&lt;/code&gt;在&lt;code&gt;commit&lt;/code&gt;之前查询得到的 ORM 对象的&lt;code&gt;_sa_instance_state.expire&lt;/code&gt;属性设置为&lt;code&gt;Flase&lt;/code&gt;，再次读取该对象属性时将重载这个对象，方法是重新调用之前的查询语句。&lt;/p&gt;
&lt;/blockquote&gt;</description></item><item><title>sqlmodel单与多数据库连接</title><link>https://www.kutake.top/archives/sqlmodel%E5%8D%95%E4%B8%8E%E5%A4%9A%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5/</link><pubDate>Sat, 11 Mar 2023 01:48:02 +0800</pubDate><guid>https://www.kutake.top/archives/sqlmodel%E5%8D%95%E4%B8%8E%E5%A4%9A%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5/</guid><description>&lt;h2 id="连接单个数据库"&gt;连接单个数据库&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;sqlmodel&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SQLModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;create_engine&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 表&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Hero&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SQLModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;primary_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;secret_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 连接&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create_engine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;sqlite:///database.db&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 建表&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;SQLModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="连接多个数据库"&gt;连接多个数据库&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;sqlmodel&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SQLModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;create_engine&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;sqlmodel.main&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;registry&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 表1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;table1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Hero1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SQLModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;table1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;primary_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;secret_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 表2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;table2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Hero2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SQLModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;table2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;primary_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;secret_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 连接1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;engine1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create_engine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;sqlite:///database1.db&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 连接2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;engine2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create_engine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;sqlite:///database2.db&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 建表1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Hero1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;engine1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 建表2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Hero2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;engine2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="一点优化"&gt;一点优化&lt;/h2&gt;
&lt;p&gt;显然这样建多表会很麻烦，一种优化方案是：&lt;/p&gt;</description></item><item><title>sqlalchemy异步与同步方式获取自增id</title><link>https://www.kutake.top/archives/sqlalchemy%E5%BC%82%E6%AD%A5%E4%B8%8E%E5%90%8C%E6%AD%A5%E6%96%B9%E5%BC%8F%E8%8E%B7%E5%8F%96%E8%87%AA%E5%A2%9Eid/</link><pubDate>Thu, 05 Jan 2023 00:19:10 +0800</pubDate><guid>https://www.kutake.top/archives/sqlalchemy%E5%BC%82%E6%AD%A5%E4%B8%8E%E5%90%8C%E6%AD%A5%E6%96%B9%E5%BC%8F%E8%8E%B7%E5%8F%96%E8%87%AA%E5%A2%9Eid/</guid><description>&lt;h2 id="同步"&gt;同步&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# sync_session&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# example(id, name)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;name1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# id = 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="异步"&gt;异步&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# async_session&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# example(id, name)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;name1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;refresh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# id = 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>bot的一些反思</title><link>https://www.kutake.top/archives/bot%E7%9A%84%E4%B8%80%E4%BA%9B%E5%8F%8D%E6%80%9D/</link><pubDate>Sun, 25 Sep 2022 15:50:04 +0800</pubDate><guid>https://www.kutake.top/archives/bot%E7%9A%84%E4%B8%80%E4%BA%9B%E5%8F%8D%E6%80%9D/</guid><description>&lt;h2 id="模块化"&gt;模块化&lt;/h2&gt;
&lt;p&gt;我现在是这样的&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Bot&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;└─&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;└─&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;└─&lt;/span&gt;&lt;span class="n"&gt;modules&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;└─&lt;/span&gt;&lt;span class="n"&gt;utils&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;config&lt;/code&gt;内包含所有模块用到的配置项&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;db&lt;/code&gt;内是实体类和业务语句的集合&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;utils&lt;/code&gt;内是一些公共工具&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;现在问题是，&lt;code&gt;config&lt;/code&gt;与&lt;code&gt;db&lt;/code&gt;非常难维护，一打开就是几百行语句，找起来都麻烦，数据库和配置项有一点不对整个bot就无法启动&lt;/p&gt;</description></item><item><title>PDM-更现代的python包管理器</title><link>https://www.kutake.top/archives/pdm-%E6%9B%B4%E7%8E%B0%E4%BB%A3%E7%9A%84python%E5%8C%85%E7%AE%A1%E7%90%86%E5%99%A8/</link><pubDate>Tue, 31 May 2022 15:57:23 +0800</pubDate><guid>https://www.kutake.top/archives/pdm-%E6%9B%B4%E7%8E%B0%E4%BB%A3%E7%9A%84python%E5%8C%85%E7%AE%A1%E7%90%86%E5%99%A8/</guid><description>&lt;h2 id="pdm介绍"&gt;PDM介绍&lt;/h2&gt;
&lt;p&gt;一个现代的 Python 包管理器，支持 &lt;a href="https://www.python.org/dev/peps/pep-0582"&gt;PEP 582&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;跟pipenv与poetry有着相同功能&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;抛弃传统包管理器所需的虚拟环境 - &lt;a href="https://www.python.org/dev/peps/pep-0582"&gt;PEP 582&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;比poetry更快的依赖解析&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;类似pnpm的中心化安装缓存&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;插件系统&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.python.org/dev/peps/pep-0621"&gt;PEP 621&lt;/a&gt; 元数据格式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;兼容 &lt;a href="https://www.python.org/dev/peps/pep-0517"&gt;PEP 517&lt;/a&gt; 的构建后端，用于构建发布包(源码格式与 wheel 格式)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Python中便捷的上下文管理器contextmanager</title><link>https://www.kutake.top/archives/python%E4%B8%AD%E4%BE%BF%E6%8D%B7%E7%9A%84%E4%B8%8A%E4%B8%8B%E6%96%87%E7%AE%A1%E7%90%86%E5%99%A8contextmanager/</link><pubDate>Sat, 14 May 2022 20:36:57 +0800</pubDate><guid>https://www.kutake.top/archives/python%E4%B8%AD%E4%BE%BF%E6%8D%B7%E7%9A%84%E4%B8%8A%E4%B8%8B%E6%96%87%E7%AE%A1%E7%90%86%E5%99%A8contextmanager/</guid><description>&lt;h2 id="基本的上下文管理器"&gt;基本的上下文管理器&lt;/h2&gt;
&lt;p&gt;需要定义：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-Python" data-lang="Python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ContextM&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__enter__&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dosomethings&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__exit__&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dosometings&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AsyncContextM&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__aenter__&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;dosometings&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__aexit__&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;dosometings&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;调用时使用&lt;code&gt;with ContextM()&lt;/code&gt;或&lt;code&gt;async with AsyncContextM&lt;/code&gt;&lt;/p&gt;
&lt;h2 id="contextmanager"&gt;ContextManager&lt;/h2&gt;
&lt;p&gt;Python内置的一个很方便的生成上下文管理器的装饰器&lt;/p&gt;</description></item><item><title>在fastapi中使用loguru记录日志</title><link>https://www.kutake.top/archives/%E5%9C%A8fastapi%E4%B8%AD%E4%BD%BF%E7%94%A8loguru%E8%AE%B0%E5%BD%95%E6%97%A5%E5%BF%97/</link><pubDate>Sat, 12 Mar 2022 17:54:22 +0800</pubDate><guid>https://www.kutake.top/archives/%E5%9C%A8fastapi%E4%B8%AD%E4%BD%BF%E7%94%A8loguru%E8%AE%B0%E5%BD%95%E6%97%A5%E5%BF%97/</guid><description>&lt;h2 id="日志重写"&gt;日志重写&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pprint&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pformat&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;loguru&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;config&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InterceptHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Get corresponding Loguru level if it exists&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;levelname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;levelno&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Find caller from where originated the logged message&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;depth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentframe&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f_code&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;co_filename&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f_back&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;depth&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;depth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exc_info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getMessage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;format_record&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;format_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LOG_FORMAT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;extra&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;payload&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;extra&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;payload&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;extra&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;payload&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;compact&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;format_string&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;level&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{extra[payload]}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/level&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;format_string&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;{exception}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;format_string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# it requires app init or won&amp;#39;t be work&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;logger_init&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;log_path_all&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LOG_FILE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;log_path_error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log_error_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LOG_FILE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handlers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;InterceptHandler&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;sink&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;level&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;format&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;format_record&lt;/span&gt;&lt;span class="p"&gt;}])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# logger.add(config.LOG_DIR, encoding=&amp;#39;utf-8&amp;#39;, rotation=&amp;#34;9:46&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log_path_all&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;rotation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;00:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;retention&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;2 week&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;enqueue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;diagnose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;DEBUG&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;format_record&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log_path_error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;rotation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;00:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;retention&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;3 week&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;enqueue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;backtrace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;diagnose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ERROR&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;format_record&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;日志系统已加载&lt;/span&gt;&lt;span class="se"&gt;\n\n\n&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;uvicorn.access&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handlers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;InterceptHandler&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="在app中调用"&gt;在app中调用&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# app create frist, then init logger&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;logger_init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;origins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;http://127.0.0.1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://127.0.0.1:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;http://localhost&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://localhost:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# &amp;#34;*&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;include_router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scraper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;include_router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;works&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;include_router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;CORSMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;allow_origins&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;origins&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;allow_credentials&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;allow_methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;allow_headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;uvicorn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;main:app&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;0.0.0.0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;reload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# should be False at production&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;access_log&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ws_ping_interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ws_ping_timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>FastApi使用jwt-token进行验证</title><link>https://www.kutake.top/archives/fastapi%E4%BD%BF%E7%94%A8jwt-token%E8%BF%9B%E8%A1%8C%E9%AA%8C%E8%AF%81/</link><pubDate>Sat, 12 Mar 2022 17:48:58 +0800</pubDate><guid>https://www.kutake.top/archives/fastapi%E4%BD%BF%E7%94%A8jwt-token%E8%BF%9B%E8%A1%8C%E9%AA%8C%E8%AF%81/</guid><description>&lt;h2 id="以depends的方式定义jwt"&gt;以Depends的方式定义jwt&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;jose&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;JWTError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;passlib.context&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CryptContext&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;fastapi.security&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OAuth2PasswordBearer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Curd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;config&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;utils&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_db&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pwd_context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CryptContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;schemes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;bcrypt&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;auto&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;oauth2_schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OAuth2PasswordBearer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokenUrl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/users/login&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hash_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plain_password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;pwd_context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plain_password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;verity_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plain_password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hashed_password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;pwd_context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plain_password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hashed_password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;jwt_authenticate_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_db&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Curd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_user_by_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__anext__&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;verity_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;created_access_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expires_delta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;to_encode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;expires_delta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;expire&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utcnow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;expires_delta&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;expire&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utcnow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ACCESS_TOKEN_EXPIRE_MINUTES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;to_encode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;exp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;expire&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;encoded_jwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;claims&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;to_encode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SECRET_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;algorithm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;HS256&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;encoded_jwt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;jwt_verity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oauth2_schema&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;credentials_exception&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTP_401_UNAUTHORIZED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Could not validate credentials&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;WWW-Authenticate&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Bearer&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;playload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SECRET_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;algorithms&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;HS256&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;JWTError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;验证出现错误:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;credentials_exception&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;playload&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;jwt_get_current_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jwt_verity&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_db&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playload&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;sub&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Curd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_user_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__anext__&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;jwt_verity_admin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jwt_verity&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_db&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playload&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;sub&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;is_admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;playload&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;is_admin&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;is_admin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Curd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_user_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__anext__&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_admin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTP_401_UNAUTHORIZED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Could not validate credentials&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;WWW-Authenticate&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Bearer&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="需要分发token的url"&gt;需要分发token的url&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;APIRouter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/users&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;user&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# it defind at dependencies.jwt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# oauth2_schema = OAuth2PasswordBearer(tokenUrl=&amp;#34;/users/token&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@router.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/register&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;UserToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;user_register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;OAuth2PasswordRequestForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AsyncSession&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_db&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Curd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_user_name_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTP_400_BAD_REQUEST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;username already exists&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;hashed_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hash_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;new_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_id&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;hashed_password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Curd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@router.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/login&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;UserToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;user_login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;OAuth2PasswordRequestForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;jwt_authenticate_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTP_401_UNAUTHORIZED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Incorrect username or password&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;WWW-Authenticate&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Bearer&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;access_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;created_access_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;sub&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;user_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;access_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;access_token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;token_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;bearer&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user_token&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="需要token进行访问限制的url"&gt;需要token进行访问限制的url&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;APIRouter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/works&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;works&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@router.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/get&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Works&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;nsfw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jwt_get_current_user&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AsyncSession&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_db&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;works&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Curd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_works&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nsfw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;works&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Sqlalchemy-关于PyhtonORM的各种事</title><link>https://www.kutake.top/archives/sqlalchemy-%E5%85%B3%E4%BA%8Epyhtonorm%E7%9A%84%E5%90%84%E7%A7%8D%E4%BA%8B/</link><pubDate>Sat, 12 Mar 2022 17:27:57 +0800</pubDate><guid>https://www.kutake.top/archives/sqlalchemy-%E5%85%B3%E4%BA%8Epyhtonorm%E7%9A%84%E5%90%84%E7%A7%8D%E4%BA%8B/</guid><description>&lt;h2 id="orm"&gt;ORM&lt;/h2&gt;
&lt;p&gt;ORM：对象关系映射（Object Relational Mapping，简称ORM，或O/RM，或O/R mapping)，用于实现面向对象编程语言里不同类型系统的数据之间的转换&lt;/p&gt;</description></item><item><title>哈夫曼编码的实现(python)</title><link>https://www.kutake.top/archives/%E5%93%88%E5%A4%AB%E6%9B%BC%E7%BC%96%E7%A0%81%E7%9A%84%E5%AE%9E%E7%8E%B0python/</link><pubDate>Sun, 21 Nov 2021 21:31:23 +0800</pubDate><guid>https://www.kutake.top/archives/%E5%93%88%E5%A4%AB%E6%9B%BC%E7%BC%96%E7%A0%81%E7%9A%84%E5%AE%9E%E7%8E%B0python/</guid><description>&lt;!-- toc --&gt;
&lt;h2 id="思路"&gt;思路&lt;/h2&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://www.kutake.top/media/2021/11/%E5%93%88%E5%A4%AB%E6%9B%BC%E7%BC%96%E7%A0%81%E5%AE%9E%E7%8E%B0%EF%BC%88python%EF%BC%89-1024x332.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;del&gt;C++实在是弄不懂&lt;/del&gt;&lt;/p&gt;
&lt;h2 id="代码"&gt;代码&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;from typing import List, Optional
class Node:
&amp;#34;&amp;#34;&amp;#34;
结点
&amp;#34;&amp;#34;&amp;#34;
def __init__(self):
self.name: Optional[str] = None
self.weight: Optional[int] = None
self.left_child: Optional[Node] = None
self.right_child: Optional[Node] = None
self.parent: Optional[Node] = None
class NodeCode:
&amp;#34;&amp;#34;&amp;#34;
结点的编码
&amp;#34;&amp;#34;&amp;#34;
def __init__(self, name: str, code: str):
self.name = name
self.code = code
def __str__(self):
return f&amp;#34;{self.name}:{self.code}&amp;#34;
class HaffumanTreeCode:
&amp;#34;&amp;#34;&amp;#34;
哈夫曼树的编码
&amp;#34;&amp;#34;&amp;#34;
def __init__(self):
self.code_list: List[NodeCode] = []
def append(self, code: NodeCode):
self.code_list.append(code)
def code(self, massage: str):
&amp;#34;&amp;#34;&amp;#34;
针对编码表编码
:param massage: 需要编码的信息
:return:
&amp;#34;&amp;#34;&amp;#34;
code = &amp;#34;&amp;#34;
for i in massage:
for n in self.code_list:
if n.name == i:
code += n.code
break
# raise ValueError(f&amp;#34;&amp;#39;{i}&amp;#39;不存在&amp;#34;)
return code
def decode(self, code: str):
&amp;#34;&amp;#34;&amp;#34;
针对编码表解码
:param code:需要解码的哈夫曼码
:return:
&amp;#34;&amp;#34;&amp;#34;
out = &amp;#34;&amp;#34;
i = 0
while code:
code_need_match = code[0:i+1]
for n in self.code_list:
if n.code == code_need_match:
out += n.name
code = code[i+1:]
i = 0
break
i += 1
return out
def __str__(self):
&amp;#34;&amp;#34;&amp;#34;
打印
:return:
&amp;#34;&amp;#34;&amp;#34;
out = &amp;#34;&amp;#34;
for i in self.code_list:
out += i.__str__() + &amp;#34;\n&amp;#34;
return out.strip()
class HaffumanTree:
&amp;#34;&amp;#34;&amp;#34;
哈夫曼树
&amp;#34;&amp;#34;&amp;#34;
def __init__(self):
self.root = Node()
self.nodes: List[Node] = []
self.nodes_raw: List[Node] = []
self.codes: HaffumanTreeCode = HaffumanTreeCode()
def inser(self, newnode: Node):
for i in range(len(self.nodes)):
if self.nodes[i].weight &amp;lt; newnode.weight:
self.nodes.insert(i, newnode)
return
self.nodes.append(newnode)
def build_tree(self, name_list: List[str], weight_list: List[int]):
&amp;#34;&amp;#34;&amp;#34;
创建哈夫曼树
:param name_list: 字符列表
:param weight_list: 权重列表
:return:
&amp;#34;&amp;#34;&amp;#34;
# 队每个字符生成结点
while len(name_list) &amp;gt; 0:
max_weight = max(weight_list)
max_index = weight_list.index(max_weight)
max_name = name_list[max_index]
newnode = Node()
newnode.name = max_name
newnode.weight = max_weight
self.nodes.append(newnode)
name_list.remove(max_name)
weight_list.remove(max_weight)
# 保存源结点
self.nodes_raw = self.nodes[:]
# 创建新结点并生成树
while len(self.nodes) &amp;gt; 2:
left = self.nodes.pop()
right = self.nodes.pop()
newnode = Node()
newnode.weight = left.weight + right.weight
newnode.left_child = left
newnode.right_child = right
left.parent = newnode
right.parent = newnode
# 根据权重插入
self.inser(newnode)
left = self.nodes.pop()
right = self.nodes.pop()
self.root.weight = left.weight + right.weight
self.root.left_child = left
self.root.right_child = right
left.parent = self.root
right.parent = self.root
def make_code(self):
&amp;#34;&amp;#34;&amp;#34;
生成编码表
:return:
&amp;#34;&amp;#34;&amp;#34;
while len(self.nodes_raw):
node = self.nodes_raw.pop()
name = node.name
code = &amp;#34;&amp;#34;
while node.parent != self.root:
parent = node.parent
if parent.left_child == node:
code = &amp;#34;0&amp;#34; + code
elif parent.right_child == node:
code = &amp;#34;1&amp;#34; + code
node = parent
if self.root.left_child == node:
code = &amp;#34;0&amp;#34; + code
elif self.root.right_child == node:
code = &amp;#34;1&amp;#34; + code
self.codes.append(NodeCode(name, code))
def decode(self, code: str):
return self.codes.decode(code)
def code(self, massage: str):
return self.codes.code(massage)
if __name__ == &amp;#39;__main__&amp;#39;:
h = HaffumanTree()
name_list = [&amp;#34;a&amp;#34;, &amp;#34;b&amp;#34;, &amp;#34;c&amp;#34;, &amp;#34;d&amp;#34;, &amp;#34;e&amp;#34;]
wight_list = [5, 11, 6, 21, 19]
h.build_tree(name_list, wight_list)
h.make_code()
print(f&amp;#34;编码表：\n{h.codes}&amp;#34;)
print(f&amp;#39;bcacce编码为：{h.code(&amp;#34;bcacce&amp;#34;)}&amp;#39;)
print(f&amp;#39;01001000001001解码为： {h.decode(&amp;#34;0100100000100110&amp;#34;)}&amp;#39;)
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>PyMySQL基础使用</title><link>https://www.kutake.top/archives/pymysql%E5%9F%BA%E7%A1%80%E4%BD%BF%E7%94%A8/</link><pubDate>Fri, 13 Aug 2021 13:56:12 +0800</pubDate><guid>https://www.kutake.top/archives/pymysql%E5%9F%BA%E7%A1%80%E4%BD%BF%E7%94%A8/</guid><description>&lt;!-- toc --&gt;
&lt;h2 id="安装"&gt;安装&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;pip install PyMySQL
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="连接"&gt;连接&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;db = pymysql.connect(host=&amp;#34;192.168.1.1&amp;#34;, port=3306, user=&amp;#34;root&amp;#34;, password=&amp;#34;password&amp;#34;, database=&amp;#34;database_name&amp;#34;)
cursor = db.cursor()
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="查增"&gt;查/增&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sql_insert = &amp;#34;&amp;#34;&amp;#34;
INSERT INTO 表名(id, name, path)
VALUES (%s, %s, %s)
&amp;#34;&amp;#34;&amp;#34;
# 无论数据库数据类型为int或date，全部使用py的字符串形式插入，所以使用%s
cursor.execute(sql_insert, (user_id, name, path)) # 这种可以有效避免因敏感字符而导致出现语法错误
db.commit() # 进行提交，否则无效
# 当数据源为http相关时，注意转义
import html
from pymysql.converters import escape_string
safe_data = escape_string(html.unescape(unsafe_data)) # unescape转义html字符，escape转义为可直接插入数据库的安全字符串
# 多数据一次插入
cursor.executemany(sql, info) # info可为list，循环按顺序进行插入
db.commit()
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="以及"&gt;以及&lt;/h2&gt;
&lt;p&gt;因为图库已经快20g了，为了管理方便，顺便就上了mysql做数据管理，但有个问题，pymysql非异步，可能会造成bot的io堵塞，现在的数据量查询速度还算快，但要是时间久了就不一定；&lt;/p&gt;</description></item><item><title>FastApi应用-bot中挂载web服务</title><link>https://www.kutake.top/archives/fastapi%E5%BA%94%E7%94%A8-bot%E4%B8%AD%E6%8C%82%E8%BD%BDweb%E6%9C%8D%E5%8A%A1/</link><pubDate>Tue, 15 Jun 2021 19:34:04 +0800</pubDate><guid>https://www.kutake.top/archives/fastapi%E5%BA%94%E7%94%A8-bot%E4%B8%AD%E6%8C%82%E8%BD%BDweb%E6%9C%8D%E5%8A%A1/</guid><description>&lt;!-- toc --&gt;
&lt;h2 id="轻量web服务"&gt;轻量web服务&lt;/h2&gt;
&lt;h3 id="介绍"&gt;介绍&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;FastAPI 是一个用于构建 API 的现代、快速（高性能）的 web 框架，使用 Python 3.6+ 并基于标准的 Python 类型提示。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;FastAPI 框架，高性能，易于学习，高效编码，生产可用&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;</description></item><item><title>all() 一个便利的多条件判断方法</title><link>https://www.kutake.top/archives/all-%E4%B8%80%E4%B8%AA%E4%BE%BF%E5%88%A9%E7%9A%84%E5%A4%9A%E6%9D%A1%E4%BB%B6%E5%88%A4%E6%96%AD%E6%96%B9%E6%B3%95/</link><pubDate>Tue, 04 May 2021 13:43:48 +0800</pubDate><guid>https://www.kutake.top/archives/all-%E4%B8%80%E4%B8%AA%E4%BE%BF%E5%88%A9%E7%9A%84%E5%A4%9A%E6%9D%A1%E4%BB%B6%E5%88%A4%E6%96%AD%E6%96%B9%E6%B3%95/</guid><description>&lt;h2 id="一般的多条件判断"&gt;一般的多条件判断&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;if 判断1 and 判断2 and 判断3:
run()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;当语句非常长的时候，就显得难懂且不美观&lt;/p&gt;
&lt;h2 id="all方法多条件判断"&gt;all()方法多条件判断&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;if all([条件1, 条件2, 条件3]):
run()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;all()传入一个可迭代对象，当所有条件为True时，返回True&lt;/p&gt;</description></item><item><title>CUAVbot--一个python构成的qq机器人</title><link>https://www.kutake.top/archives/cuavbot-%E4%B8%80%E4%B8%AApython%E6%9E%84%E6%88%90%E7%9A%84qq%E6%9C%BA%E5%99%A8%E4%BA%BA/</link><pubDate>Mon, 03 May 2021 01:39:59 +0800</pubDate><guid>https://www.kutake.top/archives/cuavbot-%E4%B8%80%E4%B8%AApython%E6%9E%84%E6%88%90%E7%9A%84qq%E6%9C%BA%E5%99%A8%E4%BA%BA/</guid><description>&lt;p&gt;这个bot写了有段小时间了，一直没有做个总结之类的，正好最近使用了&lt;a href="https://github.com/GraiaProject/Saya"&gt;saya&lt;/a&gt;, &lt;del&gt;代码算是可以看了点&lt;/del&gt;，于是就准备做个小总结。&lt;/p&gt;
&lt;!-- toc --&gt;
&lt;h2 id="bot是什么"&gt;Bot是什么&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;输入 - 处理 - 结果&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;大致上就是如此，发送一句话，bot根据这句话进行处理，然后得到预期结果。很明显，bot就是IO密集型程序，使用异步的方式是最便捷也是最高效的，这里就要说下开发框架&lt;/p&gt;</description></item><item><title>pip 换源与临时换源</title><link>https://www.kutake.top/archives/pip-set%E6%8D%A2%E6%BA%90/</link><pubDate>Fri, 19 Mar 2021 18:52:42 +0800</pubDate><guid>https://www.kutake.top/archives/pip-set%E6%8D%A2%E6%BA%90/</guid><description>&lt;h2 id="永久换源"&gt;永久换源&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;pip config set global.index-url https://
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="临时换源"&gt;临时换源&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;pip install --index-url https:// module
pip install module -i https://
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="常用源"&gt;常用源&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;清华大学 &lt;a href="https://pypi.tuna.tsinghua.edu.cn/simple/"&gt;https://pypi.tuna.tsinghua.edu.cn/simple/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;阿里云 &lt;a href="http://mirrors.aliyun.com/pypi/simple/"&gt;http://mirrors.aliyun.com/pypi/simple/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;中国科技大学 &lt;a href="https://pypi.mirrors.ustc.edu.cn/simple/"&gt;https://pypi.mirrors.ustc.edu.cn/simple/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;豆瓣(douban) &lt;a href="http://pypi.douban.com/simple/"&gt;http://pypi.douban.com/simple/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;中国科学技术大学 &lt;a href="http://pypi.mirrors.ustc.edu.cn/simple/"&gt;http://pypi.mirrors.ustc.edu.cn/simple/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;其中中国科技大学还挺好&lt;/p&gt;</description></item><item><title>模拟登录相关</title><link>https://www.kutake.top/archives/%E6%A8%A1%E6%8B%9F%E7%99%BB%E5%BD%95%E7%9B%B8%E5%85%B3/</link><pubDate>Wed, 05 Aug 2020 00:26:05 +0800</pubDate><guid>https://www.kutake.top/archives/%E6%A8%A1%E6%8B%9F%E7%99%BB%E5%BD%95%E7%9B%B8%E5%85%B3/</guid><description>&lt;p&gt;一个网页不需要登录，就可以随意访问网站的所有具体信息的话，那就好比是一个敞开了大门的网站，摆好酒桌好吃好喝招待爬虫脚本们，数据提取的成本非常低。于是比较常规的网站，都会使用账号登录来提高网站对于每个想要查看网站数据的门槛，所以模拟登陆的问题就是必修课&lt;/p&gt;</description></item><item><title>Scrapy+随机User-Again+随机高匿代理ip爬取全球最大的同人网站上万条信息</title><link>https://www.kutake.top/archives/scrapy%E9%9A%8F%E6%9C%BAuser-again%E9%9A%8F%E6%9C%BA%E9%AB%98%E5%8C%BF%E4%BB%A3%E7%90%86ip%E7%88%AC%E5%8F%96%E5%85%A8%E7%90%83%E6%9C%80%E5%A4%A7%E7%9A%84%E5%90%8C%E4%BA%BA%E7%BD%91%E7%AB%99%E4%B8%8A/</link><pubDate>Thu, 30 Jul 2020 00:48:22 +0800</pubDate><guid>https://www.kutake.top/archives/scrapy%E9%9A%8F%E6%9C%BAuser-again%E9%9A%8F%E6%9C%BA%E9%AB%98%E5%8C%BF%E4%BB%A3%E7%90%86ip%E7%88%AC%E5%8F%96%E5%85%A8%E7%90%83%E6%9C%80%E5%A4%A7%E7%9A%84%E5%90%8C%E4%BA%BA%E7%BD%91%E7%AB%99%E4%B8%8A/</guid><description>&lt;h2 id="确定需求"&gt;确定需求&lt;/h2&gt;
&lt;!-- toc --&gt;
&lt;p&gt;DLsite是全球最大的同人贩卖网站，里面包括漫画、音声、动画、游戏等等来自不同国家不同地区不同语言以及不同形式的二次元创作作品，这个项目暂定是爬取home下的所有漫画信息作为统计数据，链接为：&lt;/p&gt;</description></item><item><title>scrapy+mysql:2006错误解决方法</title><link>https://www.kutake.top/archives/scrapymysql2006%E9%94%99%E8%AF%AF%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95/</link><pubDate>Tue, 28 Jul 2020 16:27:34 +0800</pubDate><guid>https://www.kutake.top/archives/scrapymysql2006%E9%94%99%E8%AF%AF%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95/</guid><description>&lt;p&gt;首先放上piplines的代码&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;from itemadapter import ItemAdapter
import MySQLdb
import logging
class TestRjPipeline:
def __init__(self):
host = (&amp;#39;localhost&amp;#39;)
user = (&amp;#39;root&amp;#39;)
pass_ = (&amp;#39;123456&amp;#39;)
db = (&amp;#39;sqlforpy&amp;#39;)
self.connect = MySQLdb.connect(host,user,pass_,db,charset=&amp;#39;utf8mb4&amp;#39;)
self.cursor = self.connect.cursor()
def process_item(self, item, spider):
def get_data(items_):
data = dict(items_)
rj={&amp;#39;ID&amp;#39;:&amp;#39;无&amp;#39;,&amp;#39;title&amp;#39;:&amp;#39;无&amp;#39;,&amp;#39;circle&amp;#39;:&amp;#39;无&amp;#39;,&amp;#39;keyword_creater&amp;#39;:&amp;#39;无&amp;#39;,&amp;#39;data&amp;#39;:&amp;#39;无&amp;#39;,&amp;#39;sname&amp;#39;:&amp;#39;无&amp;#39;\
,&amp;#39;GEN&amp;#39;:&amp;#39;无&amp;#39;,&amp;#39;type_&amp;#39;:&amp;#39;无&amp;#39;,&amp;#39;category&amp;#39;:&amp;#39;无&amp;#39;,&amp;#39;other&amp;#39;:&amp;#39;无&amp;#39;,&amp;#39;pages&amp;#39;:&amp;#39;无&amp;#39;,&amp;#39;genre&amp;#39;:&amp;#39;无&amp;#39;,\
&amp;#39;file_&amp;#39;:&amp;#39;无&amp;#39;,&amp;#39;event&amp;#39;:&amp;#39;无&amp;#39;}
for k in data.items():
rj[k[0]] = k[1]
return rj
rj = get_data(item)
sql = r&amp;#34;&amp;#34;&amp;#34;insert into dlsite_cg_copy1(RJ,标题,社团,作者,发售日,系列名,年龄指定,文件形式,作品类型,其他,页数,分类,文件容量,活动)VALUES(&amp;#34;%s&amp;#34;,&amp;#34;%s&amp;#34;,&amp;#34;%s&amp;#34;,&amp;#34;%s&amp;#34;,&amp;#34;%s&amp;#34;,&amp;#34;%s&amp;#34;,&amp;#34;%s&amp;#34;,&amp;#34;%s&amp;#34;,&amp;#34;%s&amp;#34;,&amp;#34;%s&amp;#34;,&amp;#34;%s&amp;#34;,&amp;#34;%s&amp;#34;,&amp;#34;%s&amp;#34;,&amp;#34;%s&amp;#34;)&amp;#34;&amp;#34;&amp;#34;% (rj[&amp;#39;ID&amp;#39;],rj[&amp;#39;title&amp;#39;],rj[&amp;#39;circle&amp;#39;],rj[&amp;#39;keyword_creater&amp;#39;],rj[&amp;#39;data&amp;#39;],rj[&amp;#39;sname&amp;#39;],rj[&amp;#39;GEN&amp;#39;],rj[&amp;#39;type_&amp;#39;],rj[&amp;#39;category&amp;#39;],rj[&amp;#39;other&amp;#39;],rj[&amp;#39;pages&amp;#39;],rj[&amp;#39;genre&amp;#39;],rj[&amp;#39;file_&amp;#39;],rj[&amp;#39;event&amp;#39;])
try:
self.cursor.execute(sql)
self.connect.commit()
except:
logging.debug(&amp;#39;%s写入数据库出现错误！&amp;#39;%rj[&amp;#39;ID&amp;#39;])
logging.debug(&amp;#39;内容为:\n{}\n&amp;#39;.format(rj))
self.connect.rollback()
logging.debug(&amp;#39;此次保存操作结束&amp;#39;)
def close_spider(self, spider):
self.cursor.close()
self.connect.close()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;start之后，总是只能&lt;strong&gt;保存第一条信息&lt;/strong&gt;，然后一直显示&lt;strong&gt;2006&lt;/strong&gt;错误&lt;/p&gt;</description></item><item><title>关于ValueError: too many values to unpack错误</title><link>https://www.kutake.top/archives/%E5%85%B3%E4%BA%8Evalueerror-too-many-values-to-unpack%E9%94%99%E8%AF%AF/</link><pubDate>Mon, 27 Jul 2020 14:38:07 +0800</pubDate><guid>https://www.kutake.top/archives/%E5%85%B3%E4%BA%8Evalueerror-too-many-values-to-unpack%E9%94%99%E8%AF%AF/</guid><description>&lt;p&gt;在写scrapy的时候遇到的一个坑，准备了一个由“无”元素作为value的字典作为蓝本，遍历从scrapy上得到的items字典数据，把其中有的元素放到第一个作为蓝本的字典中，于是这里就有两个操作，读取第二个字典，修改第一个字典&lt;/p&gt;</description></item><item><title>实战：comic walker漫画多章节爬虫</title><link>https://www.kutake.top/archives/python%E5%AE%9E%E6%88%98comic-walker%E6%BC%AB%E7%94%BB%E5%A4%9A%E7%AB%A0%E8%8A%82%E7%88%AC%E8%99%AB/</link><pubDate>Wed, 15 Jul 2020 10:57:00 +0800</pubDate><guid>https://www.kutake.top/archives/python%E5%AE%9E%E6%88%98comic-walker%E6%BC%AB%E7%94%BB%E5%A4%9A%E7%AB%A0%E8%8A%82%E7%88%AC%E8%99%AB/</guid><description>&lt;h2 id="为什么要做"&gt;为什么要做&lt;/h2&gt;
&lt;p&gt;还在做汉化组的扒图的时候，一直觉得comic walker这个站点的漫画拔起来非常麻烦，因为它自带一个阅读器界面，异步加载图片，而且无法右键，甚至在网页元素中，也无法直接保存图片（这应该是漫画网站的常见配置了），只能一个个在控制台中拖动图片至新的标签页才能加载图片并保存，十分麻烦，正好学习python中，就写了这个小工具。&lt;/p&gt;</description></item><item><title>json文件转xls文件</title><link>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%989json%E6%96%87%E4%BB%B6%E8%BD%ACxls%E6%96%87%E4%BB%B6/</link><pubDate>Sat, 27 Jun 2020 14:26:12 +0800</pubDate><guid>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%989json%E6%96%87%E4%BB%B6%E8%BD%ACxls%E6%96%87%E4%BB%B6/</guid><description>&lt;pre tabindex="0"&gt;&lt;code&gt;#写成json的文本文件内容，转换为xls文件
import xlwt
import os
import json
def get_(path):
with open(path,&amp;#39;r&amp;#39;,encoding=&amp;#39;utf-8&amp;#39;) as f:
content=f.read()
return content
def json_(str):
d=json.loads(str)
d=sorted(d.items(),key=lambda item:item[0],reverse=False)
return d
def json_16(str):
d=json.loads(str)
return d
def save_(d,path):
workbook=xlwt.Workbook(encoding=&amp;#39;utf-8&amp;#39;)
sheet1=workbook.add_sheet(&amp;#39;sheet1&amp;#39;)
r=0
c=1
for key,value in d:
sheet1.write(r,0,key)
for i in value:
sheet1.write(r,c,i)
c+=1
r+=1
c=1
workbook.save(path)
def save_16(d,path):
workbook=xlwt.Workbook(encoding=&amp;#39;utf-8&amp;#39;)
sheet1=workbook.add_sheet(&amp;#39;sheet1&amp;#39;)
for a,b in enumerate(d):
for c,v in enumerate(b):
sheet1.write(a,c,v)
workbook.save(path)
if __name__ == &amp;#34;__main__&amp;#34;:
p1=r&amp;#39;E:\vscode\code\testwork\txtfile\5.txt&amp;#39;
p2=r&amp;#39;E:\vscode\code\testwork\txtfile\5.xls&amp;#39;
save_16(json_16(get_(p1)),p2)
print(&amp;#39;END&amp;#39;)
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>实战：词云生成</title><link>https://www.kutake.top/archives/python%E5%AE%9E%E6%88%98%E8%AF%8D%E4%BA%91%E7%94%9F%E6%88%90/</link><pubDate>Sat, 27 Jun 2020 14:21:00 +0800</pubDate><guid>https://www.kutake.top/archives/python%E5%AE%9E%E6%88%98%E8%AF%8D%E4%BA%91%E7%94%9F%E6%88%90/</guid><description>&lt;pre tabindex="0"&gt;&lt;code&gt;import re
import jieba
import collections
import numpy as np
import wordcloud # 词云展示库
from PIL import Image # 图像处理库
import matplotlib.pyplot as plt # 图像展示库
def remove():
with open(&amp;#39;remove_words.txt&amp;#39;,&amp;#39;r&amp;#39;,encoding=&amp;#39;utf-8&amp;#39;) as f:
txt=f.read()
words = re.findall(r&amp;#39;[^\s]+&amp;#39;,txt)
list_=[]
for i in words:
if i in list_:
continue
else:
list_.append(i)
return list_
def get_words(path):
f=open(path,encoding=&amp;#39;utf-8&amp;#39;)
txt=f.read()
f.close()
words = jieba.lcut(txt)
remove_word=remove()
reword = []
for word in words:
if len(word) == 1:
continue
elif word in remove_word:
continue
else:
reword.append(word)
word_counts=collections.Counter(reword)
return word_counts
#统计词频
def wordcount(word_counts):
top=word_counts.most_common(20)
print(top)
def wordc(impath,words):
mask=np.array(Image.open(impath))
wc = wordcloud.WordCloud(
font_path=&amp;#39;C:/Windows/Fonts/simhei.ttf&amp;#39;, # 设置字体格式
mask=mask, # 设置背景图
max_words=600, # 最多显示词数
max_font_size=130 # 字体最大值
)
wc.generate_from_frequencies(words) # 从字典生成词云
image_colors = wordcloud.ImageColorGenerator(mask) # 从背景图建立颜色方案
wc.recolor(color_func=image_colors) # 将词云颜色设置为背景图方案
plt.imshow(wc) # 显示词云
plt.axis(&amp;#39;off&amp;#39;) # 关闭坐标轴
plt.show() # 显示图像
wc.to_file(&amp;#39;ff.png&amp;#39;)
if __name__ == &amp;#34;__main__&amp;#34;:
path=r&amp;#39;E:\vscode\code\ff.txt&amp;#39;
impath=r&amp;#39;E:\vscode\code\topdodo_2.jpg&amp;#39;
wordc(impath,get_words(path))
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>实战：RJ爬虫并上传本地SQL</title><link>https://www.kutake.top/archives/rj%E7%88%AC%E8%99%AB%E4%B8%8A%E4%BC%A0%E6%9C%AC%E5%9C%B0sql/</link><pubDate>Sat, 27 Jun 2020 14:18:00 +0800</pubDate><guid>https://www.kutake.top/archives/rj%E7%88%AC%E8%99%AB%E4%B8%8A%E4%BC%A0%E6%9C%AC%E5%9C%B0sql/</guid><description>&lt;p&gt;下载了上百个RJ后，如何根据声优或分类喜好来找到自己喜欢的作品就成了个问题，于是诞生出了这个代码&lt;/p&gt;
&lt;h2 id="问题拆分"&gt;&lt;strong&gt;问题拆分&lt;/strong&gt;&lt;/h2&gt;
&lt;h3 id="定位需求"&gt;定位需求&lt;/h3&gt;
&lt;p&gt;查询RJ主要是在对该RJ文件夹对应网页中的标题、声优、制作社团与分类，拿到具体数据后，对数据进行查询操作。&lt;/p&gt;</description></item><item><title>生成四位验证码并验证</title><link>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%987%E7%94%9F%E6%88%90%E5%9B%9B%E4%BD%8D%E9%AA%8C%E8%AF%81%E7%A0%81%E5%B9%B6%E9%AA%8C%E8%AF%81/</link><pubDate>Sat, 27 Jun 2020 14:15:00 +0800</pubDate><guid>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%987%E7%94%9F%E6%88%90%E5%9B%9B%E4%BD%8D%E9%AA%8C%E8%AF%81%E7%A0%81%E5%B9%B6%E9%AA%8C%E8%AF%81/</guid><description>&lt;pre tabindex="0"&gt;&lt;code&gt;#四位数数字字母验证码，显示进行输入判断验证
from PIL import Image, ImageFilter, ImageFont,ImageDraw
import os
import random
import string
import matplotlib.pyplot as plt
# ImageFilter:Python中的图像滤波，主要对图像进行平滑、锐化、边界增强等滤波处理。
#随机选取一个数字字母，含大小写
def get_word():
word = string.ascii_letters+string.digits
return random.choice(word)
#字体像素随机颜色
def font_color():
#random.randint()在范围内取随机数
return(random.randint(32,255),random.randint(23,255),random.randint(32,255))
#背景像素随机颜色
def b_color():
return(random.randint(64,255),random.randint(64,255),random.randint(64,255))
#生成验证码图像，返回一个字符串，表示验证码
def imag(path):
w = 60*4
h = 60
d_word=&amp;#39;&amp;#39;
#新建图像对象
img = Image.new(&amp;#39;RGB&amp;#39;,(w,h),(255,255,255))
#字体对象
font = ImageFont.truetype(r&amp;#39;H:\gay化\汉化\字体\4书法 - 2\FZ宋s刻d本r秀d楷繁.ttf&amp;#39;,60)
#类似于画笔
draw = ImageDraw.Draw(img)
for i in range(w):
for j in range(h):
#画背景，用随机颜色填充每个像素
draw.point((i,j),fill=b_color())
for i in range(4):
word=get_word()
#draw.text方法进行字符绘图，()内：绘图位置，字符，字体，颜色
draw.text((i*60+10,5),word,font=font,fill=font_color())
#单个验证码相加
d_word = d_word + word
#保存验证码图像
img.save(path,&amp;#39;jpeg&amp;#39;)
#返回验证码
return d_word
#一个输入函数，调用时返回输入内容
def get_input():
return str(input(&amp;#39;请输入验证码:\n&amp;#39;))
#运行
if __name__ == &amp;#34;__main__&amp;#34;:
path = (&amp;#39;test.jpg&amp;#39;)
str_=imag(path)
test_img=Image.open(path)
plt.figure(&amp;#39;test&amp;#39;)
plt.imshow(test_img)
plt.show()
#四次机会
for i in range(4):
if str.lower(str_) == str.lower(get_input()):
print(&amp;#39;验证成功&amp;#39;)
break
else:
if i == 3:
print(&amp;#39;错误次数已用完！&amp;#39;)
else:
print(&amp;#39;错误！还有%d次机会&amp;#39;%(3-i))
#结束后删除验证码图像
os.remove(path)
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>图片等比例缩放实现</title><link>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%984%E5%9B%BE%E7%89%87%E7%AD%89%E6%AF%94%E4%BE%8B%E7%BC%A9%E6%94%BE/</link><pubDate>Sat, 27 Jun 2020 14:11:00 +0800</pubDate><guid>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%984%E5%9B%BE%E7%89%87%E7%AD%89%E6%AF%94%E4%BE%8B%E7%BC%A9%E6%94%BE/</guid><description>&lt;pre tabindex="0"&gt;&lt;code&gt;#设定一个分辨率，使一个文件夹内所有大于该分辨率的图像都进行等比例缩放
import os
import re
from PIL import Image
#设置目录
f_path = &amp;#39;E:/vscode/code/testwork/testFile&amp;#39;
#设置iPhone5的分辨率
i_high = 640
i_width = 1136
#使用os.listdir()方法，将目录内的图像文件名，以列表的形式存入list
list=os.listdir(f_path)
#设置计数初始值
count = 0
#对每个文件进行判断
for pic in list:
#path为完整的图像文件路径
path=f_path+&amp;#39;/&amp;#39;+pic
#使用Image.open()方法，打开图像文件
im=Image.open(path)
#im.size方法获得图像的宽高，分别存入w,h
w,h=im.size
#当宽度大于i5
if w &amp;gt; i_width:
#这里判断：原图像哪边大则依据哪边作为等比缩放比例
if w&amp;gt;h:
w_new = i_width
h_new = int(h*i_width/w)
else:
w_new = int(w*i_high/h)
h_new = i_high
print(&amp;#39;%s被修改&amp;#39; %pic)
#使用resize()方法修改分辨率，((w,h),此处Image.ANTIALIAS表示高质量)
out = im.resize((w_new,h_new),Image.ANTIALIAS)
#使用re.sub方法，在字符串pic中，开头至倒数第四位字符替换为添加_new的字符串
newpic = re.sub(pic[:-4],pic[:-4]+&amp;#39;_new&amp;#39;,pic)
#处理后的图像的完整保存路径
new_path = f_path+&amp;#39;/&amp;#39;+newpic
#save方法保存
out.save(new_path)
#处理完毕计数+1
count = count + 1
elif h &amp;gt; i_high:
if w&amp;gt;h:
w_new = i_width
h_new = int(h*i_width/w)
else:
w_new = int(w*i_high/h)
h_new = i_high
print(&amp;#39;%s被修改&amp;#39; %pic)
out = im.resize((w_new,h_new),Image.ANTIALIAS)
newpic = re.sub(pic[:-4],pic[:-4]+&amp;#39;_new&amp;#39;,pic)
new_path = f_path+&amp;#39;/&amp;#39;+newpic
out.save(new_path)
count = count + 1
print(&amp;#39;处理结束\n总共有%d个文件被处理&amp;#39; %count)
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>实战：通话统计及简易图表制作</title><link>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%80%9A%E8%AF%9D%E7%BB%9F%E8%AE%A1%E5%8F%8A%E7%AE%80%E6%98%93%E5%9B%BE%E8%A1%A8%E5%88%B6%E4%BD%9C/</link><pubDate>Sat, 27 Jun 2020 14:08:00 +0800</pubDate><guid>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%80%9A%E8%AF%9D%E7%BB%9F%E8%AE%A1%E5%8F%8A%E7%AE%80%E6%98%93%E5%9B%BE%E8%A1%A8%E5%88%B6%E4%BD%9C/</guid><description>&lt;p&gt;最开始的看到的python基础习题之一，现在顺便扩展一点，练习xlrd、pandas以及matplotlib的练习&lt;/p&gt;
&lt;h2 id="数据来源"&gt;数据来源&lt;/h2&gt;
&lt;p&gt;来自于联通官网的通话数据下载，文件为某年某月的通话记录详情，格式为xls**[图片缺失: 2020/06/QQ截图20200627215145.png]**&lt;!-- broken-image: 2020/06/QQ截图20200627215145.png --&gt;&lt;/p&gt;</description></item><item><title>文本识别屏蔽词转换</title><link>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%988%E6%96%87%E6%9C%AC%E8%AF%86%E5%88%AB%E5%B1%8F%E8%94%BD%E8%AF%8D%E8%BD%AC%E6%8D%A2/</link><pubDate>Sat, 27 Jun 2020 14:01:00 +0800</pubDate><guid>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%988%E6%96%87%E6%9C%AC%E8%AF%86%E5%88%AB%E5%B1%8F%E8%94%BD%E8%AF%8D%E8%BD%AC%E6%8D%A2/</guid><description>&lt;pre tabindex="0"&gt;&lt;code&gt;#2020/3/10
#设置一个屏蔽词文本，输入一段字符串，将其中的屏蔽词转换成*
import re
#参数为路径，返回整个屏蔽词文本
def get_f(path):
f = open(path,&amp;#39;r&amp;#39;,encoding=&amp;#39;utf-8&amp;#39;)
art=f.read()
f.close()
return art
#参数为字符串，返回一个屏蔽词列表
def get_list(str):
list_=[]
word = re.findall(r&amp;#39;[^\s]+&amp;#39;,str)
for i in word:
list_.append(i.lower())
return list_
#参数i为输入，b为屏蔽词列表
def pri(i,b):
ww=[]
ww.append(i)
h=0
for n in b:
if re.findall(n,ww[h]) != []:
s=&amp;#39;*&amp;#39;*len(n)
p = re.sub(n,s,ww[h])
h+=1
ww.append(p)
if h != 0:
#print(&amp;#39;共替换了%d个词&amp;#39;%h)
return ww[h]
else:
return i
#run
if __name__ == &amp;#34;__main__&amp;#34;:
path=r&amp;#39;E:\vscode\code\ban.txt&amp;#39;
b=get_list(get_f(path))
#print(b)
i=str(input(&amp;#39;输入：\n&amp;#39;))
print(pri(i,b))
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>随机码生成</title><link>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%982%E9%9A%8F%E6%9C%BA%E7%A0%81%E7%94%9F%E6%88%90/</link><pubDate>Fri, 26 Jun 2020 14:16:19 +0800</pubDate><guid>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%982%E9%9A%8F%E6%9C%BA%E7%A0%81%E7%94%9F%E6%88%90/</guid><description>&lt;pre tabindex="0"&gt;&lt;code&gt;#生成自定义数量由大小写字母与数字随机组成的号码/激活码，然后存入mysql数据库
import random
import string
import MySQLdb
#获取号码
def GenKey(length): #length为号码长度
chars = string.ascii_letters + string.digits #string.ascii.letters是26个英文字母的大小写[a-z A-Z],string.digits为[0-9]相加作为字典
return &amp;#39;&amp;#39;.join([random.choice(chars) for i in range(length)])
#拿出chars内的一个字符并重复进行length次，将得到的字符与空字符串相加，得到长度为length的号码
#保存号码
def SaveKey(content):
f = open(&amp;#39;Result Key.txt&amp;#39;, &amp;#39;a&amp;#39;)
#打开Result Key.txt，a表示“打开一个文件用于追加。如果该文件已存在，文件指针将会放在文件的结尾。”
f.write(content)
#写入一个content，此处为号码
f.write(&amp;#39;\n&amp;#39;)
#换行
f.close()
#关闭
#保存至mysql数据库
def save_sql(code_nu):
host = (&amp;#34;localhost&amp;#34;)
user = (&amp;#34;root&amp;#34;)
pass_ = (&amp;#34;123456&amp;#34;)
db = (&amp;#34;sqlforpy&amp;#34;)
#建立连接
connect = MySQLdb.connect(host,user,pass_,db)
#使用cursor()方法获取操作游标 （在操作游标中才可进行数据库操作
cursor = connect.cursor()
#使用insert into进行插入数据
sql = &amp;#34;insert into code(code)VALUES(&amp;#39;%s&amp;#39;)&amp;#34; % code_nu
#执行sql语句
cursor.execute(sql)
#使用commit提交到数据库执行保存
connect.commit()
#关闭连接
connect.close()
if __name__ == &amp;#39;__main__&amp;#39;:
length=int(input(&amp;#34;\n请输入需要的号码个数：&amp;#34;))
for i in range(length):
value = GenKey(20)
print (value)
#SaveKey(value)
save_sql(value)
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>统计英文单词词频</title><link>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%983%E7%BB%9F%E8%AE%A1%E8%8B%B1%E6%96%87%E5%8D%95%E8%AF%8D%E8%AF%8D%E9%A2%91/</link><pubDate>Wed, 24 Jun 2020 14:18:03 +0800</pubDate><guid>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%983%E7%BB%9F%E8%AE%A1%E8%8B%B1%E6%96%87%E5%8D%95%E8%AF%8D%E8%AF%8D%E9%A2%91/</guid><description>&lt;pre tabindex="0"&gt;&lt;code&gt;#读取一个纯英文的文本文件，统计其中每个单词的出现次数，并将次数和其单词本身存入mysql数据库
import re
import MySQLdb
#读取文件信息
filename=&amp;#34;word.txt&amp;#34;
#使用open方法操作文本文件，r表示以只读方式打开文件。文件的指针将会放在文件的开头
f=open(filename,&amp;#39;r&amp;#39;)
#使用f.read方法返回整个文本文件给article，
artical=f.read()
#使用f.close关闭文件
f.close()
#将文本中的所有英文单词筛选出来 去掉标点和其他文本符号 并且将单词都小写保存在数组List中
List=[]
#&amp;#39;[a-zA-Z]+&amp;#39;正则表达式，表示大小写a-z出现一次或连续出现，这里表达一个单词
#使用re.findall方法，从article中获取单词，作为list存入word中
word=re.findall(&amp;#39;[a-zA-Z]+&amp;#39;,artical)
for i in word:
List.append(i.lower())
#把单词与出现的次数存入数据库（我也不知道为什么要存进去:)
def save_sql(word,numbers):
host = (&amp;#34;localhost&amp;#34;)
user = (&amp;#34;root&amp;#34;)
pass_ = (&amp;#34;123456&amp;#34;)
db = (&amp;#34;sqlforpy&amp;#34;)
#建立连接
connect = MySQLdb.connect(host,user,pass_,db)
#使用cursor()方法获取操作游标 （在操作游标中才可进行数据库操作
cursor = connect.cursor()
#使用insert into进行插入数据
sql = &amp;#34;insert into count_word(word,numbers)VALUES(&amp;#39;%s&amp;#39;,&amp;#39;%d&amp;#39;)&amp;#34; % (word,numbers)
#执行sql语句
try:
cursor.execute(sql)
#使用commit提交到数据库执行保存
connect.commit()
except:
#发生错误时回滚
connect.rollback()
#关闭连接
connect.close()
#统计单词数目
print(&amp;#34;%s总共有%d个单词&amp;#34; %(filename,List.__len__()))
#统计各个单词出现的频率，并且按照字典顺序输出并将内容写入文件中
#f=open(&amp;#34;result.txt&amp;#34;,&amp;#39;w&amp;#39;)
List=sorted(List)
i=0
for i in range(0,List.__len__()-1):
#使用count方法获得字符串出现的次数
count=List.count(List[i])
if(List[i]!=List[i+1]):
#print(List[i]+&amp;#34; &amp;#34;+str(count)+&amp;#34;\n&amp;#34;)
#f.write(List[i]+&amp;#34; &amp;#34;+str(count)+&amp;#34;\n&amp;#34;)
save_sql(List[i],count)
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>统计文件夹内所有文件的词频</title><link>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%985%E7%BB%9F%E8%AE%A1%E6%96%87%E4%BB%B6%E5%A4%B9%E5%86%85%E6%89%80%E6%9C%89%E6%96%87%E4%BB%B6%E7%9A%84%E8%AF%8D%E9%A2%91/</link><pubDate>Tue, 23 Jun 2020 14:20:22 +0800</pubDate><guid>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%985%E7%BB%9F%E8%AE%A1%E6%96%87%E4%BB%B6%E5%A4%B9%E5%86%85%E6%89%80%E6%9C%89%E6%96%87%E4%BB%B6%E7%9A%84%E8%AF%8D%E9%A2%91/</guid><description>&lt;pre tabindex="0"&gt;&lt;code&gt;#在一个文件夹内存放着几个纯英文文本，统计其中出现次数最多的单词
import os
import re
f_dir=&amp;#39;E:/vscode/code/testwork/txtfile&amp;#39;
f_list=os.listdir(f_dir)
List=[]
dict={}
#传入文件名，返回文本文件路径
def get_f(name):
return f_dir+&amp;#39;/&amp;#39;+name
#传入文件路径，返回文件内文本（字符串
def open_f(fdir):
f = open(fdir,&amp;#39;r&amp;#39;,encoding=&amp;#39;UTF-8&amp;#39;)
artical=f.read()
f.close()
return artical
#传入字符串，找出其中的单词统一小写，并以list形式添加到List中
def get_w(file):
word=re.findall(&amp;#39;[a-zA-Z]+&amp;#39;,file)
for i in word:
List.append(i.lower())
#传入一个list，将其排序后，提取每个单词与其出现的次数，以字典形式存放于dict
def get_c(w_list):
s_list=sorted(w_list)
i = 0
for i in range(0,s_list.__len__()-1):
count=s_list.count(s_list[i])
if(s_list[i]!=s_list[i+1]):
dict[s_list[i]]=count
if __name__ == &amp;#34;__main__&amp;#34;:
art=&amp;#39;&amp;#39;
for i in f_list:
f_path=get_f(i)
art=art+open_f(f_path)
get_w(art)
get_c(List)
#用max方法找出字典内values最大的值
highest=max(dict.values())
print(&amp;#39;所有文件共有%d个单词&amp;#39;%List.__len__())
print(&amp;#39;出现最多次的单词：&amp;#39;)
#用最大值去提取与其相匹配的key，得到一个或多个出现次数最高的单词
print([k for k,v in dict.items() if v == highest])
print(&amp;#39;总共出现了%d次&amp;#39;%highest)
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>统计文件夹内所有代码文件的代码行、注释行和空行</title><link>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%986%E7%BB%9F%E8%AE%A1%E6%96%87%E4%BB%B6%E5%A4%B9%E5%86%85%E6%89%80%E6%9C%89%E4%BB%A3%E7%A0%81%E6%96%87%E4%BB%B6%E7%9A%84%E4%BB%A3%E7%A0%81%E8%A1%8C/</link><pubDate>Mon, 22 Jun 2020 14:22:01 +0800</pubDate><guid>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%986%E7%BB%9F%E8%AE%A1%E6%96%87%E4%BB%B6%E5%A4%B9%E5%86%85%E6%89%80%E6%9C%89%E4%BB%A3%E7%A0%81%E6%96%87%E4%BB%B6%E7%9A%84%E4%BB%A3%E7%A0%81%E8%A1%8C/</guid><description>&lt;pre tabindex="0"&gt;&lt;code&gt;#有一个文件夹内存放着代码文件，统计所有文件的代码行，注释行和空行的总数
import os
def j_anno(line):
if line.strip().startswith(&amp;#34;#&amp;#34;):
return True
else:
return False
def j_annos(line):
if line.strip().startswith(&amp;#34;&amp;#39;&amp;#39;&amp;#39;&amp;#34;) or line.strip().startswith(&amp;#39;&amp;#34;&amp;#34;&amp;#34;&amp;#39;):
return True
else:
return False
path=&amp;#39;E:/vscode/code/testwork&amp;#39;
code_line=0
comm_line=0
space_line=0
for root,dirs,files in os.walk(path):
for item in files:
f_path=os.path.join(root,item)
f_exten=os.path.splitext(f_path)[1]
if f_exten == &amp;#39;.py&amp;#39;:
with open(f_path,&amp;#39;r&amp;#39;,encoding=&amp;#39;utf-8&amp;#39;) as fp:
#print(&amp;#39;key:&amp;#39;,key)
#print(&amp;#39;value:&amp;#39;,value)
while True:
line=fp.readline()
if not line:
break
elif j_anno(line):
comm_line +=1
elif j_annos(line):
while True:
line=fp.readline()
if j_annos(line):
break
else:
comm_line +=1
elif line.strip():
code_line+=1
else:
space_line+=1
#test
print(&amp;#39;目录：%s总共有:\n%d行代码\n%d行注释\n%d个空行&amp;#39;%(path,code_line,comm_line,space_line))
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>哈希加密验证尝试</title><link>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%9810%E5%93%88%E5%B8%8C%E5%8A%A0%E5%AF%86%E9%AA%8C%E8%AF%81/</link><pubDate>Sun, 21 Jun 2020 14:27:06 +0800</pubDate><guid>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%9810%E5%93%88%E5%B8%8C%E5%8A%A0%E5%AF%86%E9%AA%8C%E8%AF%81/</guid><description>&lt;pre tabindex="0"&gt;&lt;code&gt;#加入随机salt的哈希运算验证
import random
from hashlib import sha256
from hmac import HMAC
#意义在于，随机halt哈希混淆运算后的数据极难被反推出密码原文，彩虹字典的暴力破解难度极大
#参数r_pass为密码原文，salt可选，返回一个带slat与加密后的字符串
def get_pass(r_pass,salt=None):
if salt == None:
salt=sha256(str(random.random()).encode(&amp;#39;utf-8&amp;#39;)).hexdigest()[-8:]
#先生成一个HMAC()对象，然后再调用digest()生成hash之后的结果
password=HMAC(salt.encode(&amp;#39;utf-8&amp;#39;),r_pass.encode(&amp;#39;utf-8&amp;#39;),sha256).hexdigest()
return (&amp;#39;%s$%s&amp;#39;%(salt,password))
#参数r_pass为再次输入的原文密码，password为第一次哈希后的字符串
def check_pass(r_pass,password):
salt=password.split(&amp;#39;$&amp;#39;)[0]
return password == get_pass(r_pass,salt)
#run
if __name__ == &amp;#34;__main__&amp;#34;:
password=input(&amp;#39;请输入密码：\n&amp;#39;)
p=get_pass(password)
while True:
pass_=input(&amp;#39;请再次输入密码：\n&amp;#39;)
if check_pass(pass_,p):
print(&amp;#39;密码正确&amp;#39;)
break
else:
print(&amp;#39;密码错误&amp;#39;)
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>未读消息图标模拟</title><link>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%981%E6%9C%AA%E8%AF%BB%E6%B6%88%E6%81%AF%E5%9B%BE%E6%A0%87%E6%A8%A1%E6%8B%9F/</link><pubDate>Fri, 29 May 2020 14:15:00 +0800</pubDate><guid>https://www.kutake.top/archives/python%E7%BB%83%E4%B9%A0%E9%A2%981%E6%9C%AA%E8%AF%BB%E6%B6%88%E6%81%AF%E5%9B%BE%E6%A0%87%E6%A8%A1%E6%8B%9F/</guid><description>&lt;pre tabindex="0"&gt;&lt;code&gt;from PIL import Image,ImageFont,ImageDraw
import sys
reload(sys) #必须要reload
sys.setdefaultencoding(&amp;#39;utf-8&amp;#39;) #字符编码改为utf8
headPath=r&amp;#34;&amp;#34;
#头像图片路径
output=r&amp;#34;&amp;#34;
#处理后输出路径
fontPath=r&amp;#34;&amp;#34;
#字体路径
headFile=&amp;#34;&amp;#34; #头像文件
outFile=&amp;#34;&amp;#34; #输出文件
#打开图片建立画布
image=Image.open(headPath+headFile,r)
draw=ImageDraw.Draw(image)
#由图片大小确定字体大小
fontsize=min(image.size)/4
#增加文字
fontobj=ImageFont.truetype(font=fontPath+&amp;#34;AdobeHeisistd-Regular.otf&amp;#34;,size=fontsize,index=0,encoding=&amp;#34;,filename=None)#
&amp;#34;&amp;#34;&amp;#34;
&amp;#34;&amp;#34;&amp;#34;
from PIL import Image,ImageFont,ImageDraw#从PIL库导入所需模块
import sys
reload(sys) #必须要reload
sys.setdefaultencoding(&amp;#39;utf-8&amp;#39;)#字符编码改为utf8
headPath=r&amp;#34;E:\\vscode\\code\\testwork\\testFile\\&amp;#34;
#头像图片路径
outputPath=r&amp;#34;C:E:\\vscode\\code\\testwork\\testFile\\output\\&amp;#34;
#处理后输出路径
fontPath=r&amp;#34;C:\\Windows\\Fonts\\&amp;#34;
#字体路径
headFile=&amp;#34;head.jpg&amp;#34; #头像文件
outFile=&amp;#34;output.jpg&amp;#34; #输出文件
#打开图片，建立画布
image=Image.open(headPath+headFile,&amp;#39;r&amp;#39;)
draw=ImageDraw.Draw(image)
#由图片大小确定字体大小
fontsize=min(image.size)/4
#增加文字
fontobj=ImageFont.truetype(font=fontPath+&amp;#34;AdobeHeitiStd-Regular.otf&amp;#34;,size=fontsize,index=0,encoding=&amp;#39;&amp;#39;,filename=None)#实例字体对象
draw.text((image.size[0]-fontsize,0),text=&amp;#34;5&amp;#34;,fill=(255,0,0),font=fontobj,anchor=None)#用draw对象的text()方法添加文字
image.save(outputPath+outFile)#保存图片
&amp;#34;&amp;#34;&amp;#34;
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2016/12/12 上午10:13
# @Author : hukezhu
# @Site :
# @File : 0000:添加未读消息.py
# @Software: PyCharm
from PIL import Image, ImageDraw, ImageFont
#创建图片对象
headImage = Image.open(&amp;#39;E:/vscode/code/testwork/testFile/head.jpg&amp;#39;)
#获取图片对象的宽高
w,h = headImage.size
#创建字体对象
font = ImageFont.truetype(&amp;#39;C:/Windows/Fonts/Arial.ttf&amp;#39;,int(h/4))
#绘制圆形
ImageDraw.Draw(headImage).pieslice([(w/3*2,0),(w,h/3)],0,360,fill=&amp;#39;red&amp;#39;)
ImageDraw.Draw(headImage).text((w*0.76,h*0.02),&amp;#39;3&amp;#39;,font = font, fill = &amp;#39;white&amp;#39;)
#展示绘制结果(使用系统默认的图片浏览器)
#headImage.show()
#保存绘制结果
headImage.save(&amp;#39;E:/vscode/code/testwork/testFile/wode.jpg&amp;#39;)
&lt;/code&gt;&lt;/pre&gt;</description></item></channel></rss>