<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>涩涩发抖</title>
        <link>https://blog.haose.love//</link>
        <description>涩涩湿人进步</description>
        <lastBuildDate>Fri, 21 Mar 2025 04:29:39 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>zh-CN</language>
        <copyright>All rights reserved 2025, 昊色居士</copyright>
        <item>
            <title><![CDATA[某网站简单逆向思路]]></title>
            <link>https://blog.haose.love//article/1b0d8e83-ddeb-80d7-aa86-eaa7e32823bc</link>
            <guid>https://blog.haose.love//article/1b0d8e83-ddeb-80d7-aa86-eaa7e32823bc</guid>
            <pubDate>Sat, 08 Mar 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-1b0d8e83ddeb80d7aa86eaa7e32823bc"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-1b0d8e83ddeb800aba26fdd95821e9ce" data-id="1b0d8e83ddeb800aba26fdd95821e9ce"><span><div id="1b0d8e83ddeb800aba26fdd95821e9ce" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1b0d8e83ddeb800aba26fdd95821e9ce" title="前言"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">前言</span></span></h3><div class="notion-text notion-block-1b0d8e83ddeb80899779f76d4ebf1809">群里讨论某网站的逆向，想去试一下，于是记录下过程，实力微薄，勿怪勿怪。</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-1b0d8e83ddeb80339577e388142973cf" data-id="1b0d8e83ddeb80339577e388142973cf"><span><div id="1b0d8e83ddeb80339577e388142973cf" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1b0d8e83ddeb80339577e388142973cf" title="一 初窥"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">一 初窥</span></span></h3><div class="notion-text notion-block-1b0d8e83ddeb805a96c6f96768b987a4">先看看这个网站什么情况</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-1b0d8e83ddeb8056bda3f779f8a6951e"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A012dce88-d0bd-40cd-8499-e86f1787888a%3Aimage.png?table=block&amp;id=1b0d8e83-ddeb-8056-bda3-f779f8a6951e&amp;t=1b0d8e83-ddeb-8056-bda3-f779f8a6951e" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-1b0d8e83ddeb80b9a18fddbd73cdc8a1">可以发现只有请求头里面有加密的参数，看看启动器里面调用栈，打打断点看看</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-1b0d8e83ddeb80218892fa060fc4cba1"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A4dda9510-e5a3-43f5-86f8-e3e3fe163076%3Aimage.png?table=block&amp;id=1b0d8e83-ddeb-8021-8892-fa060fc4cba1&amp;t=1b0d8e83-ddeb-8021-8892-fa060fc4cba1" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-1b0d8e83ddeb80ab8704c36d3e3f000d"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A8ae4dacc-a66a-493c-9fee-0dbaf517a113%3Aimage.png?table=block&amp;id=1b0d8e83-ddeb-80ab-8704-c36d3e3f000d&amp;t=1b0d8e83-ddeb-80ab-8704-c36d3e3f000d" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-1b0d8e83ddeb800eb449f2d5837b16b6">可以看到这个网站是使用的 <code class="notion-inline-code">axios</code> 这个库去调用的网络请求，这个库也是个很常用的网络请求库，如果你当时并不知道这个库，你可以搜索一下，也会发现</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-1b0d8e83ddeb80dc8148d8237d99a6f0"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3Ac66b8ee4-6133-41d8-a3b8-5333e000ea09%3Aimage.png?table=block&amp;id=1b0d8e83-ddeb-80dc-8148-d8237d99a6f0&amp;t=1b0d8e83-ddeb-80dc-8148-d8237d99a6f0" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-1b0d8e83ddeb804d9687e18b1e717a8c">简单看下这个文档会发现有请求拦截器功能，这个在请求的请求头校验大概率也是在拦截器里面添加的，我们可以看下拦截器的用法</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-1b0d8e83ddeb80389e93fbb7e5ac65ca"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3Ad705fdf5-a43a-4c7c-98b0-ce2332f3032d%3Aimage.png?table=block&amp;id=1b0d8e83-ddeb-8038-9e93-fbb7e5ac65ca&amp;t=1b0d8e83-ddeb-8038-9e93-fbb7e5ac65ca" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-1b0d8e83ddeb80d4af95c2143544d988">现在去网站看下有没有拦截器的痕迹</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-1b0d8e83ddeb80f9bf8ed0a7b0e0030a"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A99e1716f-7bc3-4759-908c-1a14bd7ecca7%3Aimage.png?table=block&amp;id=1b0d8e83-ddeb-80f9-bf8e-d0a7b0e0030a&amp;t=1b0d8e83-ddeb-80f9-bf8e-d0a7b0e0030a" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-1b0d8e83ddeb806c8bdcec6397b94c67">果然是有拦截器的存在，点进去看看</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-1b0d8e83ddeb801a99c7ef9bcf88c9eb"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3Ac8bd216c-f640-47bf-b899-cdcdf46e6d42%3Aimage.png?table=block&amp;id=1b0d8e83-ddeb-801a-99c7-ef9bcf88c9eb&amp;t=1b0d8e83-ddeb-801a-99c7-ef9bcf88c9eb" alt="notion image" loading="lazy" decoding="async"/></div></figure><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-1b0d8e83ddeb80bab94bcbe9f8e6b5ce" data-id="1b0d8e83ddeb80bab94bcbe9f8e6b5ce"><span><div id="1b0d8e83ddeb80bab94bcbe9f8e6b5ce" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1b0d8e83ddeb80bab94bcbe9f8e6b5ce" title="二 深挖"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">二 深挖</span></span></h3><div class="notion-text notion-block-1b0d8e83ddeb80eab455d4230f86bf75">混淆的代码，老规矩丢进反混淆网站里面看看，结果是这样的：</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-1b0d8e83ddeb80439b09c5db225fbf6f"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A7377f75b-bae9-45d7-87dc-ddde4fcd662c%3Aimage.png?table=block&amp;id=1b0d8e83-ddeb-8043-9b09-c5db225fbf6f&amp;t=1b0d8e83-ddeb-8043-9b09-c5db225fbf6f" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-1b0d8e83ddeb80adbd68f750a0e9d56e">通过第一个地方可以发现使用方法和官方的是一样的，所以我们的思路的完全正确的，第二个地方就是请求头附加加密参数的地方，进去看看</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-1b0d8e83ddeb803d9047f82a640d7148"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A6af1e83f-c77f-4200-8768-7c1c8ab2a0fd%3Aimage.png?table=block&amp;id=1b0d8e83-ddeb-803d-9047-f82a640d7148&amp;t=1b0d8e83-ddeb-803d-9047-f82a640d7148" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-1b0d8e83ddeb80c382a6f6ba48ec9a25"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A46e94273-914d-4a1b-a0d6-c786297d2c2b%3Aimage.png?table=block&amp;id=1b0d8e83-ddeb-80c3-82a6-f6ba48ec9a25&amp;t=1b0d8e83-ddeb-80c3-82a6-f6ba48ec9a25" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-1b0d8e83ddeb800ba7dbeb954d4c485f">发现最后是这个函数给请求头设置的加密参数，入参就是请求信息，也是丢进反混淆看看，但是这个结果就不尽人意了，就手动看吧</div><div class="notion-text notion-block-1b0d8e83ddeb805fafb0c51e40da8445">通过观察就会发现这类的混淆最大的特点就是字符串加密，把固定字符串和方法名加密后使用 <code class="notion-inline-code">[]</code> 的方法去调用， <code class="notion-inline-code">_0xf2d8ea</code> 很明显就是获取字符或字符串的方法，好在这个方法比较好，咱们调试一下手动替换就好，如果长的话就 <code class="notion-inline-code">ast</code> 替换，原理是一样的，找到规律然后替换</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-1b0d8e83ddeb8065b677e71d424af9f9"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A273f8ae3-3aac-423e-977e-6b479fb21d3d%3Aimage.png?table=block&amp;id=1b0d8e83-ddeb-8065-b677-e71d424af9f9&amp;t=1b0d8e83-ddeb-8065-b677-e71d424af9f9" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-1b0d8e83ddeb80e78433dd7176ed22d2"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A24ce1818-603c-4a7c-b3a6-465cdb51db9a%3Aimage.png?table=block&amp;id=1b0d8e83-ddeb-80e7-8433-dd7176ed22d2&amp;t=1b0d8e83-ddeb-80e7-8433-dd7176ed22d2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-1b0d8e83ddeb803caa49c5f27ed241ae">就这样使用类似的方法，找到真的的名字，替换，改为方便去看的最好得到的结果是这样的：
</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-1b0d8e83ddeb80f48ef3dad216174763"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A35323a89-8f95-47ad-8fb7-800d057ec3b9%3Aimage.png?table=block&amp;id=1b0d8e83-ddeb-80f4-8ef3-dad216174763&amp;t=1b0d8e83-ddeb-80f4-8ef3-dad216174763" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-1b0d8e83ddeb8061870fd4e1a17fe588">这就很清晰了，通过查看代码可以发现 <code class="notion-inline-code">getlocal_init_time</code> 和 <code class="notion-inline-code">getserver_init_time</code> 是直接获取的localStorage里面的，观察发现界面刷新之后也没有发现改变所以这里就直接写死</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-1b0d8e83ddeb8037b31df998ce78fe91" data-id="1b0d8e83ddeb8037b31df998ce78fe91"><span><div id="1b0d8e83ddeb8037b31df998ce78fe91" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1b0d8e83ddeb8037b31df998ce78fe91" title="搞定"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">搞定</span></span></h3><div class="notion-text notion-block-1b0d8e83ddeb801bb2acff5a2e9fc144">观察发现上面主要提到了下面几种加密方法：</div><ul class="notion-list notion-list-disc notion-block-1b0d8e83ddeb8011b523fcc7605c936e"><li>JSON序列化</li></ul><ul class="notion-list notion-list-disc notion-block-1b0d8e83ddeb809dad83ee3497476950"><li>sha1哈希</li></ul><ul class="notion-list notion-list-disc notion-block-1b0d8e83ddeb808e829bcd765fef42d4"><li>hmac加密</li></ul><div class="notion-text notion-block-1b0d8e83ddeb80c7850fe780539f954e">如果自己弄的时候在其中遇到不清楚的要先去网络上搜一下用户用途，了解了之后转python就好写了.</div><div class="notion-blank notion-block-1b0d8e83ddeb80018015db641e6a57ca"> </div><div class="notion-text notion-block-1b0d8e83ddeb80bfb11dfa0c6560e3ae">完整代码</div><div class="notion-text notion-block-1b0d8e83ddeb802e897ff25b35b4f35a">运行结果</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-1b0d8e83ddeb80b19e18eb8eb5eae084"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A9098d19e-d70a-4fdc-9356-b07bc34a4e19%3Aimage.png?table=block&amp;id=1b0d8e83-ddeb-80b1-9e18-eb8eb5eae084&amp;t=1b0d8e83-ddeb-80b1-9e18-eb8eb5eae084" alt="notion image" loading="lazy" decoding="async"/></div></figure><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-1b0d8e83ddeb80b19d79cf6a65fd63f3" data-id="1b0d8e83ddeb80b19d79cf6a65fd63f3"><span><div id="1b0d8e83ddeb80b19d79cf6a65fd63f3" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1b0d8e83ddeb80b19d79cf6a65fd63f3" title="总结"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">总结</span></span></h3><ul class="notion-list notion-list-disc notion-block-1b0d8e83ddeb806ca7d7c6770041f5f6"><li>要思路清晰，先看网站是怎么写的，如果能确定如果正向开发的，逆向好好办了</li></ul><ul class="notion-list notion-list-disc notion-block-1b0d8e83ddeb802d9ca8e8ea55192aeb"><li>灵活运用搜索引擎和工具</li></ul><div class="notion-text notion-block-1b0d8e83ddeb80ba920bda18122f6d65"><code class="notion-inline-code">hssp</code> 是在下自己写的爬虫库，还未彻底完善，感兴趣的可以的看看，点个🌟也可以的，地址是这个：</div><a target="_blank" rel="noopener noreferrer" href="https://github.com/x-haose/hssp" class="notion-external notion-external-block notion-row notion-block-1b0d8e83ddeb80f48fd0d433c47ea3da"><div class="notion-external-image"><svg viewBox="0 0 260 260"><g><path d="M128.00106,0 C57.3172926,0 0,57.3066942 0,128.00106 C0,184.555281 36.6761997,232.535542 87.534937,249.460899 C93.9320223,250.645779 96.280588,246.684165 96.280588,243.303333 C96.280588,240.251045 96.1618878,230.167899 96.106777,219.472176 C60.4967585,227.215235 52.9826207,204.369712 52.9826207,204.369712 C47.1599584,189.574598 38.770408,185.640538 38.770408,185.640538 C27.1568785,177.696113 39.6458206,177.859325 39.6458206,177.859325 C52.4993419,178.762293 59.267365,191.04987 59.267365,191.04987 C70.6837675,210.618423 89.2115753,204.961093 96.5158685,201.690482 C97.6647155,193.417512 100.981959,187.77078 104.642583,184.574357 C76.211799,181.33766 46.324819,170.362144 46.324819,121.315702 C46.324819,107.340889 51.3250588,95.9223682 59.5132437,86.9583937 C58.1842268,83.7344152 53.8029229,70.715562 60.7532354,53.0843636 C60.7532354,53.0843636 71.5019501,49.6441813 95.9626412,66.2049595 C106.172967,63.368876 117.123047,61.9465949 128.00106,61.8978432 C138.879073,61.9465949 149.837632,63.368876 160.067033,66.2049595 C184.49805,49.6441813 195.231926,53.0843636 195.231926,53.0843636 C202.199197,70.715562 197.815773,83.7344152 196.486756,86.9583937 C204.694018,95.9223682 209.660343,107.340889 209.660343,121.315702 C209.660343,170.478725 179.716133,181.303747 151.213281,184.472614 C155.80443,188.444828 159.895342,196.234518 159.895342,208.176593 C159.895342,225.303317 159.746968,239.087361 159.746968,243.303333 C159.746968,246.709601 162.05102,250.70089 168.53925,249.443941 C219.370432,232.499507 256,184.536204 256,128.00106 C256,57.3066942 198.691187,0 128.00106,0 Z M47.9405593,182.340212 C47.6586465,182.976105 46.6581745,183.166873 45.7467277,182.730227 C44.8183235,182.312656 44.2968914,181.445722 44.5978808,180.80771 C44.8734344,180.152739 45.876026,179.97045 46.8023103,180.409216 C47.7328342,180.826786 48.2627451,181.702199 47.9405593,182.340212 Z M54.2367892,187.958254 C53.6263318,188.524199 52.4329723,188.261363 51.6232682,187.366874 C50.7860088,186.474504 50.6291553,185.281144 51.2480912,184.70672 C51.8776254,184.140775 53.0349512,184.405731 53.8743302,185.298101 C54.7115892,186.201069 54.8748019,187.38595 54.2367892,187.958254 Z M58.5562413,195.146347 C57.7719732,195.691096 56.4895886,195.180261 55.6968417,194.042013 C54.9125733,192.903764 54.9125733,191.538713 55.713799,190.991845 C56.5086651,190.444977 57.7719732,190.936735 58.5753181,192.066505 C59.3574669,193.22383 59.3574669,194.58888 58.5562413,195.146347 Z M65.8613592,203.471174 C65.1597571,204.244846 63.6654083,204.03712 62.5716717,202.981538 C61.4524999,201.94927 61.1409122,200.484596 61.8446341,199.710926 C62.5547146,198.935137 64.0575422,199.15346 65.1597571,200.200564 C66.2704506,201.230712 66.6095936,202.705984 65.8613592,203.471174 Z M75.3025151,206.281542 C74.9930474,207.284134 73.553809,207.739857 72.1039724,207.313809 C70.6562556,206.875043 69.7087748,205.700761 70.0012857,204.687571 C70.302275,203.678621 71.7478721,203.20382 73.2083069,203.659543 C74.6539041,204.09619 75.6035048,205.261994 75.3025151,206.281542 Z M86.046947,207.473627 C86.0829806,208.529209 84.8535871,209.404622 83.3316829,209.4237 C81.8013,209.457614 80.563428,208.603398 80.5464708,207.564772 C80.5464708,206.498591 81.7483088,205.631657 83.2786917,205.606221 C84.8005962,205.576546 86.046947,206.424403 86.046947,207.473627 Z M96.6021471,207.069023 C96.7844366,208.099171 95.7267341,209.156872 94.215428,209.438785 C92.7295577,209.710099 91.3539086,209.074206 91.1652603,208.052538 C90.9808515,206.996955 92.0576306,205.939253 93.5413813,205.66582 C95.054807,205.402984 96.4092596,206.021919 96.6021471,207.069023 Z" fill="#161614"></path></g></svg></div><div class="notion-external-description"><div class="notion-external-title">hssp</div><div class="notion-external-subtitle"><span>x-haose</span><span> • </span><span>Updated <!-- -->Jan 23, 2025</span></div></div></a><div class="notion-blank notion-block-1b0d8e83ddeb80efa81ff7242f053e9a"> </div><div class="notion-blank notion-block-1b0d8e83ddeb801ba31ddfff9e322076"> </div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Postgresql 导入导出介绍]]></title>
            <link>https://blog.haose.love//article/8e2bd3c8-1258-44ad-9bd6-ca39fa22acef</link>
            <guid>https://blog.haose.love//article/8e2bd3c8-1258-44ad-9bd6-ca39fa22acef</guid>
            <pubDate>Fri, 21 Oct 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[在我们开发过程中，经常会遇到把生产环境或测试环境的数据库导入至本地进行测试。今天这篇给大家分享一下，如果使用 Postgresql 的导出工具及导入工具完成这项工作]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-8e2bd3c8125844ad9bd6ca39fa22acef"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><div class="notion-table-of-contents notion-gray notion-block-da538a072a0a4197a1599ea376084aa9"><a href="#72947b634935494283710bcb6abf169c" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">简介</span></a><a href="#05e8283578814a3788b6f335914d0733" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">命令及工具</span></a><a href="#7fdcb2a98fee4e268b619ba6867e71f1" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">导出工具</span></a><a href="#0eeef774a02d4620a54f46530576b861" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">导入工具</span></a><a href="#6ddb9b7b252f4b39bd62119a3b077e5a" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">密码文件</span></a><a href="#9aed3128939945d1990dd77b524bbc95" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">实例测试</span></a><a href="#b7981c6cfee040ae8f237e9747c54170" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">结语</span></a></div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-72947b634935494283710bcb6abf169c" data-id="72947b634935494283710bcb6abf169c"><span><div id="72947b634935494283710bcb6abf169c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#72947b634935494283710bcb6abf169c" title="简介"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">简介</span></span></h3><div class="notion-text notion-block-a2f298e2b359493fbaea2c90f5ff9458">在我们开发过程中，经常会遇到把生产环境或测试环境的数据库导入至本地进行测试。今天这篇给大家分享一下，如果使用 Postgresql 的导出工具及导入工具完成这项工作</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-05e8283578814a3788b6f335914d0733" data-id="05e8283578814a3788b6f335914d0733"><span><div id="05e8283578814a3788b6f335914d0733" class="notion-header-anchor"></div><a class="notion-hash-link" href="#05e8283578814a3788b6f335914d0733" title="命令及工具"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">命令及工具</span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-7fdcb2a98fee4e268b619ba6867e71f1" data-id="7fdcb2a98fee4e268b619ba6867e71f1"><span><div id="7fdcb2a98fee4e268b619ba6867e71f1" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7fdcb2a98fee4e268b619ba6867e71f1" title="导出工具"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">导出工具</span></span></h4><div class="notion-text notion-block-4c16bb6c4138432bb8277f0b8997acfc">导出工具用的是<code class="notion-inline-code">pg_dump</code> ，在 Windows 平台下这个工具叫做<code class="notion-inline-code">pg_dump.exe</code>，谁用来导出指定数据库的工具，常用参数有：</div><ul class="notion-list notion-list-disc notion-block-1e80960075f84ca8a96a7db2d2c8f5e3"><li>h 指定运行服务器的主机名，就是要导出数据所在的地址</li></ul><ul class="notion-list notion-list-disc notion-block-a050ead5d4884c878b159256825aece4"><li>p 对应的端口号</li></ul><ul class="notion-list notion-list-disc notion-block-51bdc1cfbc5b4e5296822f3e3c5478ab"><li>U 有权限的一个用户名</li></ul><ul class="notion-list notion-list-disc notion-block-17b0b2c5483a4566adf537157387c7bc"><li>d 要导出的数据库名字</li></ul><ul class="notion-list notion-list-disc notion-block-b0ddbc4341b548129e6db2878c37f4d5"><li>f 保存的文件名</li></ul><ul class="notion-list notion-list-disc notion-block-40289e6090e34901b161fda3110eda66"><li>w 不发出请输入密码的问题，如果无法自动连接就会连接失败，对于我们编写自动脚本很有帮助</li></ul><ul class="notion-list notion-list-disc notion-block-143a8f5d28f5468eb68aca6aa2d1bd26"><li>F 设置导出的文件格式，可以选择：</li><ul class="notion-list notion-list-disc notion-block-143a8f5d28f5468eb68aca6aa2d1bd26"><li>Fp 纯文本 SQL 脚本文件(缺省), db.sql</li><li>Fc 适合输入到 pg_restore 里的自定义格式归档，有压缩效果 db.dump</li><li>Ft 适合输入到 pg_restore 里的<code class="notion-inline-code">tar</code>归档文件。没有压缩效果 db.tar</li></ul></ul><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-0eeef774a02d4620a54f46530576b861" data-id="0eeef774a02d4620a54f46530576b861"><span><div id="0eeef774a02d4620a54f46530576b861" class="notion-header-anchor"></div><a class="notion-hash-link" href="#0eeef774a02d4620a54f46530576b861" title="导入工具"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">导入工具</span></span></h4><div class="notion-text notion-block-140ab607fb304354a53a1678a23d88c1">导入工具有两种可以选择，分别是 psql，和 pg_restore，但是 psql 只能导入纯文本 sql 格式的数据，而 pg_restore 则可以导入任何格式的数据，在这里我们会选择使用 pg_restore 来进行导入，常用参数有：</div><ul class="notion-list notion-list-disc notion-block-cebe7152d1e24291bdd58b173f61785e"><li>h 指定运行服务器的主机名，就是要导出数据所在的地址</li></ul><ul class="notion-list notion-list-disc notion-block-8ff6cdec16ad46da89012b21c351fe7f"><li>p 对应的端口号</li></ul><ul class="notion-list notion-list-disc notion-block-79b9b7b4335646e78a3723f6db848594"><li>U 有权限的一个用户名</li></ul><ul class="notion-list notion-list-disc notion-block-5c688527b3ce4f6a989bc1b987864c0e"><li>d 要导入进去的数据库名字</li></ul><ul class="notion-list notion-list-disc notion-block-48dceea36ad743b6a8f552998627defa"><li>j 并行导入，后面数值可以是 cpu 的核心数量</li></ul><ul class="notion-list notion-list-disc notion-block-a6aead1733a546b68ef7c1a4090ce2a4"><li>F 导入的文件格式，和导出的时候相同就好</li></ul><ul class="notion-list notion-list-disc notion-block-0341505c840645f5b8e4972d68241b99"><li>要导入数据库文件</li></ul><div class="notion-text notion-block-dca808754aa9428cb3de4eee30cf9b83">要注意的是导入时，要导入一个空的数据库中，且要手动去创建这个目标数据库，虽然文档中存在<code class="notion-inline-code">-C -c</code>参数，但经过测试是没有效果的：</div><blockquote class="notion-quote notion-block-886ffde5650d4c6c8aba926a544f0496"><div>-c –clean</div><div class="notion-text notion-block-54a7fb35164d44ad848fe84e319f097d">创建数据库对象前先清理(删除)它们。（如果任一对象不在目标数据库中， 这可能会产生一些无害的错误消息。）</div><ul class="notion-list notion-list-disc notion-block-718a1184c7c74de29f6f9691212eaa87"><li>C –create</li></ul><div class="notion-text notion-block-642393875b864b56af74cbff17e1e127">在恢复数据库之前先创建它。如果也声明了<code class="notion-inline-code">--clean</code>， 那么在连接到数据库之前删除并重建目标数据库。</div><div class="notion-text notion-block-3fc2fb564b3d46598ea7e3a3ad274eb8">如果出现了这个选项，和<code class="notion-inline-code">-d</code>在一起的数据库名只是用于发出最初的 <code class="notion-inline-code">DROP DATABASE</code>和<code class="notion-inline-code">CREATE DATABASE</code>命令。 所有数据都恢复到名字出现在归档中的数据库中去。</div></blockquote><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-6ddb9b7b252f4b39bd62119a3b077e5a" data-id="6ddb9b7b252f4b39bd62119a3b077e5a"><span><div id="6ddb9b7b252f4b39bd62119a3b077e5a" class="notion-header-anchor"></div><a class="notion-hash-link" href="#6ddb9b7b252f4b39bd62119a3b077e5a" title="密码文件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">密码文件</span></span></h3><div class="notion-text notion-block-ae0ead3b63624cf8829d11636e18ae1e">由于我们是想要通过脚本去导入导出，所以采用的也是免密连接的方式，在 pgsql 中，可以通过设置密码文件：<code class="notion-inline-code">.pgpass</code>来达到免密的目的。</div><div class="notion-text notion-block-50681df7fca444f0b90e3dc91d439e54">下面是.pgpass 文件的格式：</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-9aed3128939945d1990dd77b524bbc95" data-id="9aed3128939945d1990dd77b524bbc95"><span><div id="9aed3128939945d1990dd77b524bbc95" class="notion-header-anchor"></div><a class="notion-hash-link" href="#9aed3128939945d1990dd77b524bbc95" title="实例测试"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">实例测试</span></span></h3><div class="notion-text notion-block-9ef985cdd0b248c1a53c07198f72f600">本地数据库：</div><ul class="notion-list notion-list-disc notion-block-19320b57684b4e5f9c89f09d43578af4"><li>ip: 127.0.0.1</li></ul><ul class="notion-list notion-list-disc notion-block-774783eca74549e89ed84fa04df646c6"><li>port: 5432</li></ul><ul class="notion-list notion-list-disc notion-block-30f0cfcafc9f456c8de4619fa594c4fa"><li>user：postgres</li></ul><ul class="notion-list notion-list-disc notion-block-4a5ecb8fb23346ebb099f9254e650376"><li>passwd：123456</li></ul><div class="notion-text notion-block-207cb13e27a8440f9e8a448d36c568d9">目标数据库：</div><ul class="notion-list notion-list-disc notion-block-38246a0fe48b45bcb2c64a2de5d4780a"><li>ip: 192.168.1.5</li></ul><ul class="notion-list notion-list-disc notion-block-fa3891b0f9594603be9876ff0719ca8f"><li>port: 15432</li></ul><ul class="notion-list notion-list-disc notion-block-57a10041742b48e69e13765d45a5d49b"><li>user：user11</li></ul><ul class="notion-list notion-list-disc notion-block-86eb4d2a17b743ae92193766d69ac26e"><li>passwd：abc123+</li></ul><ul class="notion-list notion-list-disc notion-block-b46f03bef1044c4d964d7d8a8f2a8a69"><li>db: video</li></ul><div class="notion-text notion-block-b1b04e68780c46b092339f080bfca766">切换用户</div><div class="notion-text notion-block-c8818383f8244e34a260e6738f934109">配置免密文件</div><div class="notion-text notion-block-b7827f92688a49c3a598d26ba021c4bd">把本地数据库和目标数据库的连接信息配置进<code class="notion-inline-code">.pgpass</code>文件中：</div><div class="notion-text notion-block-acc09ae7ebc241c48d43a32f559ecdf7">进行导出：</div><div class="notion-text notion-block-43a8c9d47ad74eeaa68e28a567e6152b">命令执行成功之后会导出至当前文件夹下，然后进行导入</div><div class="notion-text notion-block-5bb37ded3af64ff984da9f81905895c6">会注意到我们在导入的时候并没有指定 IP 地址端口号用户名之类的信息，因为我们使用的就是默认的信息，在默认的情况下，ip 为 127.0.0.1，端口号为 543，用户则默认是当前系统登陆的用户</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-b7981c6cfee040ae8f237e9747c54170" data-id="b7981c6cfee040ae8f237e9747c54170"><span><div id="b7981c6cfee040ae8f237e9747c54170" class="notion-header-anchor"></div><a class="notion-hash-link" href="#b7981c6cfee040ae8f237e9747c54170" title="结语"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">结语</span></span></h3><div class="notion-text notion-block-d4cbe006e25d416182195ce809053034">这里主要介绍了<code class="notion-inline-code">Postgresql</code>数据库的导出工具，导入工具的使用，和认证文件<code class="notion-inline-code">.pgpass</code>的介绍，希望大家有所收获！！！</div><div class="notion-blank notion-block-128d8e83ddeb805497def5eae9c9bee8"> </div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Comparison of Self-built Instant Messaging Systems]]></title>
            <link>https://blog.haose.love//article/baaf68c7-11f3-48ea-9c17-7bc8f9c98034</link>
            <guid>https://blog.haose.love//article/baaf68c7-11f3-48ea-9c17-7bc8f9c98034</guid>
            <pubDate>Fri, 26 Jan 2024 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-baaf68c711f348ea9c177bc8f9c98034"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-88f92201c3044105a859abfa85ca7253" data-id="88f92201c3044105a859abfa85ca7253"><span><div id="88f92201c3044105a859abfa85ca7253" class="notion-header-anchor"></div><a class="notion-hash-link" href="#88f92201c3044105a859abfa85ca7253" title="Comparison of Self-built Instant Messaging Systems"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Comparison of Self-built Instant Messaging Systems</span></span></h2><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-bf8d9a53171446c5a18da32dd80067b5" data-id="bf8d9a53171446c5a18da32dd80067b5"><span><div id="bf8d9a53171446c5a18da32dd80067b5" class="notion-header-anchor"></div><a class="notion-hash-link" href="#bf8d9a53171446c5a18da32dd80067b5" title="Introduction"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Introduction</span></span></h3><div class="notion-text notion-block-51081fd410534c0892eeb150194dee91">For various reasons, I wanted to deploy my own instant messaging (IM) system for around a hundred users. After researching some popular IM systems on the market, I will provide a simple comparison based on my usage scenarios. However, please note that these may not be applicable to everyone.</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-128a55b87c094ca5ace9e8c2d0c7c69c" data-id="128a55b87c094ca5ace9e8c2d0c7c69c"><span><div id="128a55b87c094ca5ace9e8c2d0c7c69c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#128a55b87c094ca5ace9e8c2d0c7c69c" title="Common IM Systems"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Common IM Systems</span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-837f4937661f49af8456e9f2cd9d8156" data-id="837f4937661f49af8456e9f2cd9d8156"><span><div id="837f4937661f49af8456e9f2cd9d8156" class="notion-header-anchor"></div><a class="notion-hash-link" href="#837f4937661f49af8456e9f2cd9d8156" title="Rocketchat"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Rocketchat</span></span></h4><div class="notion-text notion-block-150234dc0698429dad974b873945b537">Rocketchat is widely used and well-developed, with easy deployment. However, I chose not to use it because of its poor Chinese language support. Although there is a Chinese version available, it is not complete, which affects the user experience.</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-1a1fb044f6284995ba943d021f3cf084" data-id="1a1fb044f6284995ba943d021f3cf084"><span><div id="1a1fb044f6284995ba943d021f3cf084" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1a1fb044f6284995ba943d021f3cf084" title="Matrix"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Matrix</span></span></h4><div class="notion-text notion-block-8197964caa7b49269214255130be0a0e">Matrix is also widely used and has many client and server implementations. I spent a long time researching it and considered it the best solution at one point. However, there are a few drawbacks that affect the user experience:</div><ul class="notion-list notion-list-disc notion-block-ca01098ee47e4e7c8c5096da3afa4a49"><li>The Element web client has the most complete features, but it does not perform well on mobile devices.</li></ul><ul class="notion-list notion-list-disc notion-block-b6b5fec8b8c84efcbb5d778a25b2d44a"><li>Other web clients that support mobile devices.</li></ul><ul class="notion-list notion-list-disc notion-block-2e4449bead854a67942d247e236a6e16"><li>Inviting users to join a group is not user-friendly. The interface after clicking the invitation link is too complicated, and users often don&#x27;t know what to do. Therefore, manual invitation is required for each person.</li></ul><ul class="notion-list notion-list-disc notion-block-785321df440c497d9d1e121a0b7cf222"><li>End-to-end encryption, although it is a feature, is not necessary for our usage scenario. It can confuse other users who are not familiar with this feature, leading to unread messages.</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-8b6a736cf2004969b1e02ebb384bd0e3" data-id="8b6a736cf2004969b1e02ebb384bd0e3"><span><div id="8b6a736cf2004969b1e02ebb384bd0e3" class="notion-header-anchor"></div><a class="notion-hash-link" href="#8b6a736cf2004969b1e02ebb384bd0e3" title="Turms"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Turms</span></span></h4><div class="notion-text notion-block-6d238277879c45e98a8bb0f8f176ef09">Turms is an advanced open-source instant messaging engine designed for applications with 100,000 to 10 million concurrent online users. However, it does not have a user interface for clients, so I did not explore it further.</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-9215b27426484113ba7d23f372bdd63a" data-id="9215b27426484113ba7d23f372bdd63a"><span><div id="9215b27426484113ba7d23f372bdd63a" class="notion-header-anchor"></div><a class="notion-hash-link" href="#9215b27426484113ba7d23f372bdd63a" title="revolt.chat"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">revolt.chat</span></span></h4><div class="notion-text notion-block-af91032022aa49ac890572b13550d8d4">This product is similar to Discord but seems less mature and not fully developed. I will wait for further updates.</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7a82f2b3062d47b393395e17b44eea91" data-id="7a82f2b3062d47b393395e17b44eea91"><span><div id="7a82f2b3062d47b393395e17b44eea91" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7a82f2b3062d47b393395e17b44eea91" title="TangSengDaoDao"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">TangSengDaoDao</span></span></h4><div class="notion-text notion-block-32e6f71ab63345f2b76e5883a56532fb">According to its official website, TangSengDaoDao is an open-source instant messaging and chat software developed by a group of experienced developers over eight years. It claims to be an operational-level solution. I briefly reviewed it, and the interface looks appealing. However, some features, such as audio/video and file sharing, require payment.</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-7e977bd6599e4cdebe6fa4d3725587cb" data-id="7e977bd6599e4cdebe6fa4d3725587cb"><span><div id="7e977bd6599e4cdebe6fa4d3725587cb" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7e977bd6599e4cdebe6fa4d3725587cb" title="Final Choice"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Final Choice</span></span></h3><div class="notion-text notion-block-2c18ba549c864da78e21414855d27c25">In the end, I chose a chat IM system called VoceChat. Here is a brief introduction:</div><blockquote class="notion-quote notion-block-2a6ecf06af3245c39cb3f02e94042418"><div>VoceChat is a self-deployable personal cloud social media chat service. It is only 15MB in size and can be deployed on any server with minimal maintenance required. The frontend can be embedded into your own website, and all data is under the user&#x27;s control with encrypted transmission. VoceChat draws on the strengths of products and standards such as Slack, Discord, RocketChat, Solid, and Matrix, making it suitable for team communication, personal chat services, website customer support, and embedded community scenarios.</div></blockquote><div class="notion-text notion-block-e90f973575af4fa784d69a424158f7a1">Here are my impressions of using VoceChat:</div><ul class="notion-list notion-list-disc notion-block-45a90340930e456d917a2c7ac4015dea"><li>Easy deployment: Compared to Matrix, VoceChat is much easier to deploy with just a Docker container and minimal configuration.</li></ul><ul class="notion-list notion-list-disc notion-block-a35f878e26654ba89075d6aea7841be3"><li>Multi-platform support: It is available on web, Android, and iOS. The mobile adaptation of the web version is also acceptable, and although push notifications are not supported on Android, it is understandable as they are not supported on any platform.</li></ul><ul class="notion-list notion-list-disc notion-block-017c35a4284946a6b102a45091a097fd"><li>Convenient use of chatbots.</li></ul><ul class="notion-list notion-list-disc notion-block-d742c86ecdcd4a2e9ca34e03e3c782f4"><li>Clear and understandable documentation, including a Chinese version.</li></ul><ul class="notion-list notion-list-disc notion-block-99038f79b40349e1a6021bf1881b99e0"><li>Easy invitation process through registration links.</li></ul><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-02960dcd083b48b8aafdb4f615a2415e" data-id="02960dcd083b48b8aafdb4f615a2415e"><span><div id="02960dcd083b48b8aafdb4f615a2415e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#02960dcd083b48b8aafdb4f615a2415e" title="Conclusion"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Conclusion</span></span></h3><div class="notion-text notion-block-88db346de6e744f68ee665e6fa762e13">The best choice is the one that suits your needs.</div><div class="notion-blank notion-block-46e3f1ce72ef4713ac9a676f9fad80a0"> </div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Python元类浅谈之单例模式]]></title>
            <link>https://blog.haose.love//article/51ac33a5-6ed9-411e-9c07-35f109a891f7</link>
            <guid>https://blog.haose.love//article/51ac33a5-6ed9-411e-9c07-35f109a891f7</guid>
            <pubDate>Sun, 16 Oct 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[今天来带大家以单例模式为案例，给大家简单的讲解一下Python元类相关的知识]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-51ac33a56ed9411e9c0735f109a891f7"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><hr class="notion-hr notion-block-6cf6e802a61e4aa988957649dd70c15a"/><div class="notion-table-of-contents notion-gray notion-block-e074b9572ce046f3850f97fbaddcfa02"><a href="#72f6ff8afd834ca096535cc636ca3217" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">Python元类浅谈之单例模式</span></a><a href="#341c346aef074b22ac5bc451bb10bc26" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">前言</span></a><a href="#24d4f2d18bd84218a83c8abb145d0d9b" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">啥是元类</span></a><a href="#40c4cc4363b7490b9000fa989991b727" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:48px">类的创建</span></a><a href="#d8880d3e42b7467daddb10cfe0ba784d" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:48px">元类</span></a><a href="#bccc2b57a9714779963ae460dc0ed2ca" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:48px">__call__和__init__区别</span></a><a href="#aa5b0f60fc15464f81e25a012ba1c63c" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:48px">__new__和__init__区别</span></a><a href="#4c759a0aef484a0db2b288ecf3a2b968" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:48px">运行结果</span></a><a href="#6b2ef0c01161493a8ed7aef43c72f6e0" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">结语</span></a></div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-72f6ff8afd834ca096535cc636ca3217" data-id="72f6ff8afd834ca096535cc636ca3217"><span><div id="72f6ff8afd834ca096535cc636ca3217" class="notion-header-anchor"></div><a class="notion-hash-link" href="#72f6ff8afd834ca096535cc636ca3217" title="Python元类浅谈之单例模式"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Python元类浅谈之单例模式</span></span></h2><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-341c346aef074b22ac5bc451bb10bc26" data-id="341c346aef074b22ac5bc451bb10bc26"><span><div id="341c346aef074b22ac5bc451bb10bc26" class="notion-header-anchor"></div><a class="notion-hash-link" href="#341c346aef074b22ac5bc451bb10bc26" title="前言"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">前言</span></span></h3><div class="notion-text notion-block-ec4d7971b8a54470af6056f105696edd">今天来带大家以单例模式为案例，给大家简单的讲解一下Python元类相关的知识。</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-24d4f2d18bd84218a83c8abb145d0d9b" data-id="24d4f2d18bd84218a83c8abb145d0d9b"><span><div id="24d4f2d18bd84218a83c8abb145d0d9b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#24d4f2d18bd84218a83c8abb145d0d9b" title="啥是元类"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">啥是元类</span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-40c4cc4363b7490b9000fa989991b727" data-id="40c4cc4363b7490b9000fa989991b727"><span><div id="40c4cc4363b7490b9000fa989991b727" class="notion-header-anchor"></div><a class="notion-hash-link" href="#40c4cc4363b7490b9000fa989991b727" title="类的创建"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">类的创建</span></span></h4><div class="notion-text notion-block-9229f1d3551840f987d8ff931a80c929">说元类之前先说一下普通类的创建过程，众所周知，类的创建的通过<code class="notion-inline-code">class</code>关键字来进行定义一个类的，然后可以选择继承自其他的类，比如：</div><div class="notion-text notion-block-bb9a4901b0a24d928fbc2bc22c52f9cc">但也有另外一种创建类的方式，就是使用<code class="notion-inline-code">type()</code>函数，<code class="notion-inline-code">type()</code>函数有两种用法，我们来看看官方的函数签名：</div><div class="notion-text notion-block-6b86f7648aa54143a38aa974e2bfa79b">上面明确的指出了如果只传递一个参数，就是走的<code class="notion-inline-code"> type(object)</code>方法，作用是反正对象的类型，如果传递了三个函数则是使用<code class="notion-inline-code">type(name, bases, dict)</code>，作用就是创建一个新的类型，也就是类的创建，我们来看看三个参数：</div><ul class="notion-list notion-list-disc notion-block-c3a708db827c4a399d6f9fd632954519"><li>name：新类型的名字</li></ul><ul class="notion-list notion-list-disc notion-block-979642b3eb384451a2e25d5789dcd9b5"><li>bases：新类型要继承的类，类型的元组</li></ul><ul class="notion-list notion-list-disc notion-block-d10277b9df1542b1a990aaaecf646c37"><li>dict：新类型的属性</li></ul><div class="notion-text notion-block-5a53e3d793f54783a196d7a681fc0f47">我们来看一个案例：</div><div class="notion-text notion-block-6260bb8a175a40e5a5ea04d81901faf8">我们使用type创建了一个类，类型是A，继承自object类，里面没有属性，然后使用这个A创建了a、b两个对象</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-d8880d3e42b7467daddb10cfe0ba784d" data-id="d8880d3e42b7467daddb10cfe0ba784d"><span><div id="d8880d3e42b7467daddb10cfe0ba784d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#d8880d3e42b7467daddb10cfe0ba784d" title="元类"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">元类</span></span></h4><div class="notion-text notion-block-b08c77633baa47d8910740caad35b04f">由上面可以看到，我们的类A是通过type创建出来的，所以这个<code class="notion-inline-code">type</code>就是类<code class="notion-inline-code">A</code>的元类，也是所有类的默认元类，如果我们要想使用自定义的元类，就使用自己的类替换type就好，先看一下单例模式的例子：</div><div class="notion-text notion-block-68e818382cd0492ab90ec3a8ac3418e3">类<code class="notion-inline-code">SingletonMeta</code>继承自<code class="notion-inline-code">type</code>，就表示可以作为一个元类来使用，然后<code class="notion-inline-code">__call__</code>方法这里是定义在了元类里面，意思就是每次执行<code class="notion-inline-code">A()</code>的时候会调用的方法，看第一个参数<code class="notion-inline-code">cls</code>，就是使用这个元类的类，也就是<code class="notion-inline-code">A</code>，然后这个类如果不存在元类的类属性<code class="notion-inline-code">_instances</code>中，就保存进去，然后返回这个类的实例</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-bccc2b57a9714779963ae460dc0ed2ca" data-id="bccc2b57a9714779963ae460dc0ed2ca"><span><div id="bccc2b57a9714779963ae460dc0ed2ca" class="notion-header-anchor"></div><a class="notion-hash-link" href="#bccc2b57a9714779963ae460dc0ed2ca" title="__call__和__init__区别"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><code class="notion-inline-code">__call__</code>和<code class="notion-inline-code">__init__</code>区别</span></span></h4><div class="notion-text notion-block-dad4dec2313e4a74ac00300a0da03489">看到上面大家可能会有疑问<code class="notion-inline-code">A()</code>不是创建一个对象吗？这个时候不是应该执行<code class="notion-inline-code">__init__</code>方法吗？那哪个会先执行呢？一般情况下大家看到的<code class="notion-inline-code">__call__</code>是定义在普通的类里面的，也就是先实例化一个对象，然后调用对象的方式如：</div><div class="notion-text notion-block-55ce37c1c60642058cd571a2df241022">这样的情况下一定是先执行的<code class="notion-inline-code">__init__</code>方法，然后再每次执行<code class="notion-inline-code">a()</code>的时候再去调用<code class="notion-inline-code">__call__</code>方法，但是这里的<code class="notion-inline-code">__call__</code>方法是定义再元类上面的，上面说了元类的控制类的创建，所以<code class="notion-inline-code">__call__</code>方法就是再类创建成功之后，每次执行<code class="notion-inline-code">A()</code>的时候调用，这个时候类执行<code class="notion-inline-code">A() </code>的时候<code class="notion-inline-code">__init__</code>方法，只会在第一次的<code class="notion-inline-code">__call__</code>方法执行结束之后调用一次，其他的时候都会只执行<code class="notion-inline-code">__call__</code>方法</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-aa5b0f60fc15464f81e25a012ba1c63c" data-id="aa5b0f60fc15464f81e25a012ba1c63c"><span><div id="aa5b0f60fc15464f81e25a012ba1c63c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#aa5b0f60fc15464f81e25a012ba1c63c" title="__new__和__init__区别"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><code class="notion-inline-code">__new__</code>和<code class="notion-inline-code">__init__</code>区别</span></span></h4><div class="notion-text notion-block-d928f268fbc94a8bbd199425b621def5">这里面还有一个很常见的问题：<code class="notion-inline-code">__init__和__new__</code>的区别是啥，<code class="notion-inline-code">__init__</code>是类创建对象的时候去调用的方法，<b>new</b>`则是创建类的时候调用的，就拿手动创建类来说：</div><div class="notion-text notion-block-f133a5ce8c28497e9fde1e1647725242"><code class="notion-inline-code">__new__</code>方法是第二行调用的，而<code class="notion-inline-code">__init__</code>方法则是第三行调用的。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-4c759a0aef484a0db2b288ecf3a2b968" data-id="4c759a0aef484a0db2b288ecf3a2b968"><span><div id="4c759a0aef484a0db2b288ecf3a2b968" class="notion-header-anchor"></div><a class="notion-hash-link" href="#4c759a0aef484a0db2b288ecf3a2b968" title="运行结果"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">运行结果</span></span></h4><div class="notion-text notion-block-2e7e7f1fefcb444695c2584cecf223fc">上面的两种用法是相同的</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-6b2ef0c01161493a8ed7aef43c72f6e0" data-id="6b2ef0c01161493a8ed7aef43c72f6e0"><span><div id="6b2ef0c01161493a8ed7aef43c72f6e0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#6b2ef0c01161493a8ed7aef43c72f6e0" title="结语"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">结语</span></span></h3><div class="notion-text notion-block-792bb98ad6414b9ea04ac694a9d51f45">其实元类并没有那么恐怖，理解意思和过程就很清楚了，先浅谈到这里，希望大家有所收获！！！</div><div class="notion-blank notion-block-9b201d0fb4024389bb38667a4eecbd6f"> </div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Python处理Float精度问题方案]]></title>
            <link>https://blog.haose.love//article/4bc0bf09-a5d1-4adf-ac64-eba0f59cb348</link>
            <guid>https://blog.haose.love//article/4bc0bf09-a5d1-4adf-ac64-eba0f59cb348</guid>
            <pubDate>Fri, 30 Sep 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[在开发时，大家可能或多或少的在各个语言中遇到过float类型精度的问题，看着加减是没问题的，但是结果却在小数点后面出现了一堆……]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-4bc0bf09a5d14adfac64eba0f59cb348"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><div class="notion-blank notion-block-d3e1a671aba248dd8704c86925b1565e"> </div><hr class="notion-hr notion-block-32acc1d5dc4d47898e1d28218ac24f4c"/><div class="notion-table-of-contents notion-gray notion-block-1bfd9a71c007459597c6cf50ee05cf6a"><a href="#33a3eef59aa249149427c15df7f2e539" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">前言</span></a><a href="#2dee2a9253ce4085ad105b515584d6b5" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">原因</span></a><a href="#1e89022816234f678838d89cfca9547e" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">解决方案</span></a><a href="#d3fb6799c131437694ffa94902b314a4" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">转为整形</span></a><a href="#62bea08a398548ce91fdbe937f692dab" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">四舍五入</span></a><a href="#f899d7c5bb604d60bedf06ad36c02b69" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">高精度计算</span></a><a href="#76ab6f0bbbe74526945ab140308ff701" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">封装简化</span></a><a href="#d1796c14e6864729ba1f06beda76a74c" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">总结</span></a></div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-33a3eef59aa249149427c15df7f2e539" data-id="33a3eef59aa249149427c15df7f2e539"><span><div id="33a3eef59aa249149427c15df7f2e539" class="notion-header-anchor"></div><a class="notion-hash-link" href="#33a3eef59aa249149427c15df7f2e539" title="前言"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">前言</span></span></h3><div class="notion-text notion-block-f38c38f87c094ad2a825733d6332854d">在开发时，大家可能或多或少的在各个语言中遇到过<code class="notion-inline-code">float</code>类型精度的问题，看着加减是没问题的，但是结果却在小数点后面出现了一堆，像下面这样</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-8f0dcbb94dc745819e86d313113ebb57"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://images.haose.pro/notion-blog/notion-blog/a597eb95-1700287906.png?t=8f0dcbb9-4dc7-4581-9e86-d313113ebb57" alt="notion image" loading="lazy" decoding="async"/></div></figure><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-2dee2a9253ce4085ad105b515584d6b5" data-id="2dee2a9253ce4085ad105b515584d6b5"><span><div id="2dee2a9253ce4085ad105b515584d6b5" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2dee2a9253ce4085ad105b515584d6b5" title="原因"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">原因</span></span></h3><div class="notion-text notion-block-7aa3d178d68d43acabd92ab9737d5878">简单来说就是计算机在处理浮点型的时候无法准确的计算。</div><div class="notion-text notion-block-1ad432695099434fa7f510e74bfcb661">展开点说的话就是因为计算机在计算数字的时候是以二进制的形式进行的计算，而计算机是没办法把所以小数都转化为二进制的数字，所以在进行加减操作的时候出现了无法用二进制表示的小数，就会出错。</div><div class="notion-text notion-block-ccf1db96d2a74ae394ea14b69cd1084d">更加详细的原因，如果有兴趣请自行查阅资料</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-1e89022816234f678838d89cfca9547e" data-id="1e89022816234f678838d89cfca9547e"><span><div id="1e89022816234f678838d89cfca9547e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1e89022816234f678838d89cfca9547e" title="解决方案"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">解决方案</span></span></h3><div class="notion-text notion-block-6d20e8b987eb4cc6b27d0727a726f195">这里会<code class="notion-inline-code">python</code>为例写解决方案，当然其他语言也是类似的，稍加改动即可</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-d3fb6799c131437694ffa94902b314a4" data-id="d3fb6799c131437694ffa94902b314a4"><span><div id="d3fb6799c131437694ffa94902b314a4" class="notion-header-anchor"></div><a class="notion-hash-link" href="#d3fb6799c131437694ffa94902b314a4" title="转为整形"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">转为整形</span></span></h4><div class="notion-text notion-block-4ce586911f864f36be2929e78942c42e">既然小数的加减计算容易出错，乘除不容易出错，就可以把小数经过乘来转化为整数后在除一下，如下所示：</div><div class="notion-text notion-block-544e136875e743c99a58070e04f6bc35">这个操作也是存在弊端的，就是麻烦，很多涉及计算时都要这样去转一下，而且如果是中途发现存在这种问题维护起来是很不方便的，容易存在遗漏</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-62bea08a398548ce91fdbe937f692dab" data-id="62bea08a398548ce91fdbe937f692dab"><span><div id="62bea08a398548ce91fdbe937f692dab" class="notion-header-anchor"></div><a class="notion-hash-link" href="#62bea08a398548ce91fdbe937f692dab" title="四舍五入"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">四舍五入</span></span></h4><div class="notion-text notion-block-ec8d990315004856a4a2346c2a6fd66d">也是可以直接采用四舍五入的方法进行操作，在大部分的情况是适用的，如下：</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-f899d7c5bb604d60bedf06ad36c02b69" data-id="f899d7c5bb604d60bedf06ad36c02b69"><span><div id="f899d7c5bb604d60bedf06ad36c02b69" class="notion-header-anchor"></div><a class="notion-hash-link" href="#f899d7c5bb604d60bedf06ad36c02b69" title="高精度计算"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">高精度计算</span></span></h4><div class="notion-text notion-block-c0373c2ce2364d60b5b2896c755d60da">在大部分语言中都存在高精度计算类型：<code class="notion-inline-code">decimal</code>，就是专门处理需要高精度计算的情况，下面来简单的介绍一下：</div><div class="notion-text notion-block-139297cb95f443048e3a6678ee1296f2">再也不对啊，咋还是这个结果呢，上面的错误的打开方式，重新来：</div><div class="notion-text notion-block-e1c0bc2ac1e642d8bfc736444cee43c9">哎，这就对了嘛，是要把float类型专为字符串在传到Decimal中在计算就好了，当然返回的结果依旧是<code class="notion-inline-code">Decimal</code>类型的，所以就要在转成float类型：</div><div class="notion-text notion-block-fc98dc2701ba462992bd607dc2cc5bb9">由于<code class="notion-inline-code">Decimal</code>类型自身的没有提供向<code class="notion-inline-code">float</code>类型转换的方法，所以就要先转成字符串类型，在转成float类型，而<code class="notion-inline-code">to_eng_string()</code>就是把<code class="notion-inline-code">Decimal</code>专为字符串的方法</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-76ab6f0bbbe74526945ab140308ff701" data-id="76ab6f0bbbe74526945ab140308ff701"><span><div id="76ab6f0bbbe74526945ab140308ff701" class="notion-header-anchor"></div><a class="notion-hash-link" href="#76ab6f0bbbe74526945ab140308ff701" title="封装简化"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">封装简化</span></span></h4><div class="notion-text notion-block-56c411114f9246f0a8e4470763ac28d5">如果数值从计算到存储一直用都都是decimal，那当然很好，但如果还是中途转换的话，就有点麻烦了，所以我们封装一下。</div><div class="notion-text notion-block-f159033292c148d297028c04d3c96bb9">在写封装之前，要知道我们想要达成什么效果，我们要的是现有代码修改最小的形式来进行兼容，现有代码最常见的操作有：</div><ul class="notion-list notion-list-disc notion-block-4810e13a6f4d4c50b700a60caf93a136"><li>0.1+0.2</li></ul><ul class="notion-list notion-list-disc notion-block-a40b620ff7a2421e8c01e55e9ef02c41"><li>0.3-0.1</li></ul><ul class="notion-list notion-list-disc notion-block-f985098471ef403693f186a3a35b4bb0"><li>sum([0.1, 0.1, 0.1])</li></ul><div class="notion-text notion-block-e8b61da841584cbb976ee012cf123676">上面的加、减、累加是代码中出现最频繁的浮点数操作，我们就是实现这三种，前两个加和减我们使用Python里面的<code class="notion-inline-code">__add__</code>和<code class="notion-inline-code">__sub__</code>，实现这两个方法的类，就可以对类就是加和减，和其他语言里面的运算符重载很像</div><div class="notion-text notion-block-191cf3dc75394bd89ae9eaffb3a3bc78">对于累加方法<code class="notion-inline-code">sum()</code>不存在固定的主体，而且存在一个参数，目标参数是float的序列，我们可以以类的静态方法的方式去实现：<code class="notion-inline-code">@staticmethod</code></div><div class="notion-text notion-block-76b96ad4995d4e5ab160efccac6b0f55">详细代码如下：</div><div class="notion-text notion-block-6d4f13824968491cb11f660b66b19ca7">对于加和减，代码是很简单的，就是和上面操作的那样，把float转换为str，在把str转换为Decimal计算</div><div class="notion-text notion-block-dd730f04d97e434c8e22221c719adabf">对于sum方法则是，把float的序列转为Decimal的序列，然后在进行sum运算后，在把结果转为float类型</div><div class="notion-text notion-block-c98896d02b4f4ba3a50f435fbaea2fb9">使用方法：</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-d1796c14e6864729ba1f06beda76a74c" data-id="d1796c14e6864729ba1f06beda76a74c"><span><div id="d1796c14e6864729ba1f06beda76a74c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#d1796c14e6864729ba1f06beda76a74c" title="总结"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">总结</span></span></h3><div class="notion-text notion-block-d3f4903af67047409ef60dfd10880321">介绍了在Python中对于小数的精度问题的几种解决方案，虽然是以Python语言写的，但其他语言也是一样的，根据情况选择对应的方案。</div><div class="notion-blank notion-block-bd7c4afb08fe49c9b0d455337989e7aa"> </div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Python并行编程实践（上）]]></title>
            <link>https://blog.haose.love//article/7ea7f026-4b18-4dd8-801f-6abff57f9748</link>
            <guid>https://blog.haose.love//article/7ea7f026-4b18-4dd8-801f-6abff57f9748</guid>
            <pubDate>Sun, 31 Jul 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[在python中关于并行相关的也不少了，比如：进程、线程、协程、异步等等，资料也不少。我今天也来浅浅的说一下这个。]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-7ea7f0264b184dd8801f6abff57f9748"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><hr class="notion-hr notion-block-a2df48915ef443539ca1f6ef9314650b"/><div class="notion-blank notion-block-8fc1a7edc2ae453dbc82a8262faa6007"> </div><div class="notion-table-of-contents notion-gray notion-block-60aca58a6e734a9f854f4216c189bbb4"><a href="#f5746f1aae674b7d8968077af41cf592" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">前言</span></a><a href="#5b7e58f3b3ce450b872b8e2816739f9d" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">进程和线程</span></a><a href="#5f170269566b47719f520b60ee6dc95e" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">导入</span></a><a href="#176d96bae55f466e9bdf91c063edc6f9" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">实例化线程池/进程池</span></a><a href="#4fb9f74778324eeab2263876a2418105" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">submit 提交任务</span></a><a href="#20d765be0ff94270be0a52f31aa548f3" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">map 提交任务</span></a><a href="#7d8d94082d3a4b4884f1bc1024232af0" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">map 获取结果</span></a><a href="#e20595da69534bd9bc8df95685faaf33" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">submit 获取结果</span></a><a href="#114c9f5cccd74d5fb8814db04751f852" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">捕获异常</span></a><a href="#c42b172b7f3e45c8b212a0d731231c91" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">差不多了</span></a><a href="#6e2485f6e6784c53aa168c1b4189b318" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">下节继续</span></a></div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-f5746f1aae674b7d8968077af41cf592" data-id="f5746f1aae674b7d8968077af41cf592"><span><div id="f5746f1aae674b7d8968077af41cf592" class="notion-header-anchor"></div><a class="notion-hash-link" href="#f5746f1aae674b7d8968077af41cf592" title="前言"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">前言</span></span></h3><div class="notion-text notion-block-48ed68cebe0a4c1a8c15973345b2789c">在<code class="notion-inline-code">python</code>中关于并行相关的也不少了，比如：进程、线程、协程、异步等等，资料也不少。我今天也来浅浅的说一下这个。</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-5b7e58f3b3ce450b872b8e2816739f9d" data-id="5b7e58f3b3ce450b872b8e2816739f9d"><span><div id="5b7e58f3b3ce450b872b8e2816739f9d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#5b7e58f3b3ce450b872b8e2816739f9d" title="进程和线程"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">进程和线程</span></span></h3><div class="notion-text notion-block-0dac38408d684f4a888921c7c3f01268">这里准备用到的多进程和多线程均会使用<code class="notion-inline-code">concurrent.futures</code>库来实现，是 3.2 版本的出现的功能，但我相信不会人还使用着小于 3.2 版本的 python 吧，不会吧，不会吧</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-5f170269566b47719f520b60ee6dc95e" data-id="5f170269566b47719f520b60ee6dc95e"><span><div id="5f170269566b47719f520b60ee6dc95e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#5f170269566b47719f520b60ee6dc95e" title="导入"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">导入</span></span></h4><div class="notion-text notion-block-e24d8a4582f04edd923aaca1e1720e9a">在<code class="notion-inline-code">concurrent.futures</code>中线程池和进程池在使用上面是很像很像的，看起来只是引用的类不同，线程池是：<code class="notion-inline-code">ThreadPoolExecutor</code>，进程池是<code class="notion-inline-code">ProcessPoolExecutor</code>。</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-176d96bae55f466e9bdf91c063edc6f9" data-id="176d96bae55f466e9bdf91c063edc6f9"><span><div id="176d96bae55f466e9bdf91c063edc6f9" class="notion-header-anchor"></div><a class="notion-hash-link" href="#176d96bae55f466e9bdf91c063edc6f9" title="实例化线程池/进程池"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">实例化线程池/进程池</span></span></h4><div class="notion-text notion-block-6c66ff7f8f004833921897b5397bb949">一般有两种方式，一个是使用<code class="notion-inline-code">with</code>上下文管理器的方式创建，一个是直接创建对象的方式。如果是用的地方逻辑比较少，几行代码就写完了，那就直接使用<code class="notion-inline-code">with</code>上下文管理器，方便快捷不用自己关闭，如果涉及的逻辑比较复杂，用到的地方比较多就可以自己创建对象自己管理，根据需要自己选择</div><div class="notion-text notion-block-45d6863914f5455ca9e0d07a2ea5f22f">再看看参数，大部分时候需要关注的就一个<code class="notion-inline-code">max_workers</code>，代表最大工作线程/进程的数量，这个数量可以自己指定，不指定的话也会有一个默认值</div><ul class="notion-list notion-list-disc notion-block-817c4fcb4ea54991b7610a32c340b9d5"><li>ThreadPoolExecutor 的默认值为 cpu 的数量加 4，但不会大于 32</li></ul><ul class="notion-list notion-list-disc notion-block-f39111f12d2c4f1bb2ec1dfb13986775"><li>ProcessPoolExecutor 的默认值为 cpu 的数量，但在 Windows 平台上面最大不会超过 61 个</li></ul><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-4fb9f74778324eeab2263876a2418105" data-id="4fb9f74778324eeab2263876a2418105"><span><div id="4fb9f74778324eeab2263876a2418105" class="notion-header-anchor"></div><a class="notion-hash-link" href="#4fb9f74778324eeab2263876a2418105" title="submit 提交任务"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">submit 提交任务</span></span></h4><div class="notion-text notion-block-a2f0ee50465d49ddb6a8186c72ccd55a"><code class="notion-inline-code">submit</code>方法是单次提交任务，下面是函数签名：</div><div class="notion-text notion-block-724341072a484490a0b044866a890064">fn 参数是要提交的函数名字，不用加括号，<code class="notion-inline-code">*args, **kwargs</code>是函数的参数，直接写进去就行，下面看示例</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-20d765be0ff94270be0a52f31aa548f3" data-id="20d765be0ff94270be0a52f31aa548f3"><span><div id="20d765be0ff94270be0a52f31aa548f3" class="notion-header-anchor"></div><a class="notion-hash-link" href="#20d765be0ff94270be0a52f31aa548f3" title="map 提交任务"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">map 提交任务</span></span></h4><div class="notion-text notion-block-eb2322fed7714fdeaf7fdf1c68dbe4e1">上面是一个一个的提交任务，这个是批量提交任务，下面是函数签名：</div><div class="notion-text notion-block-6dc4205cbfce409e8dc6e0d2dc7911cd">大部分时候看第一个、第二个参数就行，第一个参数是要调用的函数名字，第二个是迭代器就是<code class="notion-inline-code">list、set、tuple</code>之类的，但这次这个函数默认只能穿一个参数就是迭代是数据，如下：</div><div class="notion-text notion-block-cf42f4f2e4e94b2fa0a10c042833531f">但如果你的函数真的有好几个参数，你还非要用 map，你可以使用偏函数<code class="notion-inline-code">functools.partial</code>重新构造一个函数，看例子就懂了：</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-7d8d94082d3a4b4884f1bc1024232af0" data-id="7d8d94082d3a4b4884f1bc1024232af0"><span><div id="7d8d94082d3a4b4884f1bc1024232af0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7d8d94082d3a4b4884f1bc1024232af0" title="map 获取结果"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">map 获取结果</span></span></h4><div class="notion-text notion-block-2a9265b0b7604777847f51c68e8aefdb">上面只是提交任务，提交之后任务会自动执行，先说说<code class="notion-inline-code">map</code>获取结果的方式，map 会<code class="notion-inline-code">“直接返回结果的列表”</code>，严格来说不是这样的，但可以这么理解，就是这样：</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-e20595da69534bd9bc8df95685faaf33" data-id="e20595da69534bd9bc8df95685faaf33"><span><div id="e20595da69534bd9bc8df95685faaf33" class="notion-header-anchor"></div><a class="notion-hash-link" href="#e20595da69534bd9bc8df95685faaf33" title="submit 获取结果"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">submit 获取结果</span></span></h4><div class="notion-text notion-block-e2e24f254fc04b17b01605c649a1ac67">下面在看看 submit 获取结果的方法，使用上面略有不同，稍微麻烦一点点，需要用到<code class="notion-inline-code">as_completed</code>来等待完成，直接看例子就懂了：</div><div class="notion-text notion-block-4f5c8a61d4a243c380bc7a356dc4b6c5">获取结果的时候需要使用<code class="notion-inline-code">.result()</code>方法</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-114c9f5cccd74d5fb8814db04751f852" data-id="114c9f5cccd74d5fb8814db04751f852"><span><div id="114c9f5cccd74d5fb8814db04751f852" class="notion-header-anchor"></div><a class="notion-hash-link" href="#114c9f5cccd74d5fb8814db04751f852" title="捕获异常"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">捕获异常</span></span></h4><div class="notion-text notion-block-b21adfca053c41a0b8509c92ce325399">线程池或进程池中的函数如果发生了异常，程序是不会中断的，也不会直接捕获到，比如下面：</div><div class="notion-text notion-block-0da1756bea0a4389a75dfa98dab4abf6">你会发现程序什么也没输出也没有被中止，但你如果尝试着使用捕获返回值的方式运行程序，就是发现程序抛出了异常被中止了，所以捕获异常就是在这个时候去捕获:
map 捕获异常</div><div class="notion-text notion-block-feb98f5f93e34d13b31031255e43827b">submit 捕获异常</div><div class="notion-text notion-block-3ef87feed4934091aefc00c0a59cf361">可以看出不一样的是，map 捕获异常只能在循环的外面，但 submit 在里面和外面都可以。</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-c42b172b7f3e45c8b212a0d731231c91" data-id="c42b172b7f3e45c8b212a0d731231c91"><span><div id="c42b172b7f3e45c8b212a0d731231c91" class="notion-header-anchor"></div><a class="notion-hash-link" href="#c42b172b7f3e45c8b212a0d731231c91" title="差不多了"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">差不多了</span></span></h4><div class="notion-text notion-block-1dac77656400413aa2ec95beaee901cc">如题，基本的使用差不多了就这样了，当然这个库的知识还是很多的，我只是带大家入个门，更深入的可以去看相关的文档去了解：</div><ul class="notion-list notion-list-disc notion-block-f0fdf92c14a94e03a903b8dd90a0395c"><li><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://docs.python.org/zh-cn/3/library/concurrent.futures.html">官方文档</a></li></ul><ul class="notion-list notion-list-disc notion-block-19fbf33ae18b47c2a83d1f662356871e"><li><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://python3-cookbook.readthedocs.io/zh_CN/latest/c12/p07_creating_thread_pool.html">Python Cookbook</a></li></ul><ul class="notion-list notion-list-disc notion-block-33e24db010394590a10db2235590eea2"><li><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://python-parallel-programmning-cookbook.readthedocs.io/zh_CN/latest/chapter4/02_Using_the_concurrent.futures_Python_modules.html#">python-parallel-programmning-cookbook</a></li></ul><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-6e2485f6e6784c53aa168c1b4189b318" data-id="6e2485f6e6784c53aa168c1b4189b318"><span><div id="6e2485f6e6784c53aa168c1b4189b318" class="notion-header-anchor"></div><a class="notion-hash-link" href="#6e2485f6e6784c53aa168c1b4189b318" title="下节继续"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">下节继续</span></span></h3><div class="notion-text notion-block-c4e6d39b1d274aeaa311171c5a8db436">这节就先到这里了，下节来说剩下的内容。</div></main></div>]]></content:encoded>
        </item>
    </channel>
</rss>