<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>数据库 on Lutong's Homepage</title><link>https://www.elliot98.top/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/</link><description>Recent content in 数据库 on Lutong's Homepage</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Mon, 25 Mar 2019 17:46:13 +0800</lastBuildDate><atom:link href="https://www.elliot98.top/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/index.xml" rel="self" type="application/rss+xml"/><item><title>技术摘要| 文本数据库Jardb项目总结（一）</title><link>https://www.elliot98.top/post/tech/%E6%96%87%E6%9C%AC%E6%95%B0%E6%8D%AE%E5%BA%93jardb%E9%A1%B9%E7%9B%AE%E6%80%BB%E7%BB%93/</link><pubDate>Mon, 25 Mar 2019 17:46:13 +0800</pubDate><guid>https://www.elliot98.top/post/tech/%E6%96%87%E6%9C%AC%E6%95%B0%E6%8D%AE%E5%BA%93jardb%E9%A1%B9%E7%9B%AE%E6%80%BB%E7%BB%93/</guid><description>&lt;h1 id="文本数据库jardb项目总结一"&gt;文本数据库Jardb项目总结（一）&lt;/h1&gt;
&lt;h3 id="项目地址"&gt;项目地址：&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/andytt/jardb"&gt;https://github.com/andytt/jardb&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="想法"&gt;想法&lt;/h2&gt;
&lt;p&gt;这两天时间，闲来无事，写了一个基于文件的数据库……用Python写的，效率也不能够有所期望。实现这个数据库，其实是受到了Node.js中有一个lowdb的项目的影响：文本、轻便、API极其好用。不需要支持多线程，不需要支持事务管理，不需要太多的性能。这个数据库主要还是在一些本地应用、小项目里面，提供类似应用配置管理、小型数据存储，给人以方便大概是最大的目的了吧。。。（当然最后的性能测试也超过了我的预期，见后）&lt;/p&gt;
&lt;p&gt;其实写这个项目的时候我也有自己的打算，一来用Python多练练面对对象编程。一来，体验一下开源项目的流程。所以在这个项目里面，我花了不少经历提供了详细的文档和单元测试(96%)，也算是拿出来给大家献丑了。&lt;/p&gt;
&lt;p&gt;其实在已经有一个TinyDb的Py项目了，关注的人挺多，这个项目和我的思路都差不多，自然是需要先好好研究一番，阅读完代码之后，差不多就能够开始自己动手了。&lt;/p&gt;
&lt;p&gt;设计之初我就这个几个初步的考虑，要不要使用引入事件机制、亦或者多线程的实现？大概在写完事件循环的部分之后，放弃了这个想法。倒不是因为实现困难，而是由于我的目标是对标小型化的，本地的数据库，轻便好用才是王道，负担重了反而显得不伦不类。&lt;/p&gt;
&lt;h2 id="存储格式"&gt;存储格式&lt;/h2&gt;
&lt;p&gt;存储格式的话，json是一个很好的选择：通用、方便、表达能力足够。。。另外一个就是基于pickle模块的二进制文本。最后便是直接存在内存里面。当然，作为一个超轻的框架，加密之类的功能不再实现，虽然也提供了结构，直接暴露了原始的存储格式，稍加封装，就能够实现这些功能了。最初打开数据库的时候，就需要指明数据库的文件位置和存储类型，用类似URL的格式来实现挺好的，比如:&amp;ldquo;json://database.db&amp;rdquo;……&lt;/p&gt;
&lt;p&gt;实现起来不难，用一个父类BaseStorage做接口，提供了write和read两个功能，而后由三个子类，分别实现json、pickle、memory的读写功能就行了。为了安全，存储的时候，都会将之前版本改为‘.bac’文件，且在写入的时候，先写入‘.swp’文件中，希望这样做能够提高一点安全性吧。&lt;/p&gt;
&lt;h2 id="日志"&gt;日志&lt;/h2&gt;
&lt;p&gt;日志模块，在我看来怕是这个框架的一个败笔。。。本来想实现一个适合这个数据库的日志类提供管理，最后却后悔没有直接用logging。。。只有一个类dblogging，其中根据配置的不同，可以选择把日志输出到终端或者是写进日志文件去。。。为了轻耦合，我选择了装饰器的模式：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;logs&lt;/span&gt;(self,func):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; A decorator
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; If self.log is a file path,logs will be write into it.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Otherwise if self.debug is on, logs will be printed in the terminal.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; You should know that both of them will cause the performance loss,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; especially when logs are shown in the terminal.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;wrapper&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;args, &lt;span style="color:#f92672"&gt;**&lt;/span&gt;kwargs):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;log &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;file&lt;span style="color:#f92672"&gt;.&lt;/span&gt;write(&lt;span style="color:#e6db74"&gt;&amp;#34;Jardb: function [ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;%s&lt;/span&gt;&lt;span style="color:#e6db74"&gt; ] &lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\t&lt;/span&gt;&lt;span style="color:#e6db74"&gt;args:&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\t&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;%&lt;/span&gt; func&lt;span style="color:#f92672"&gt;.&lt;/span&gt;__name__)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;file&lt;span style="color:#f92672"&gt;.&lt;/span&gt;write(str(args)&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;elif&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;debug:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#34;Jardb: function [ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;%s&lt;/span&gt;&lt;span style="color:#e6db74"&gt; ] &lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\t&lt;/span&gt;&lt;span style="color:#e6db74"&gt;args:&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;%&lt;/span&gt; func&lt;span style="color:#f92672"&gt;.&lt;/span&gt;__name__)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(args)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; func(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;args, &lt;span style="color:#f92672"&gt;**&lt;/span&gt;kwargs)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; wrapper&lt;span style="color:#f92672"&gt;.&lt;/span&gt;__doc__ &lt;span style="color:#f92672"&gt;=&lt;/span&gt; func&lt;span style="color:#f92672"&gt;.&lt;/span&gt;__doc__
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; wrapper
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;其实功能很简单，就是在调用函数之前，把函数名和相关参数全部记录下来，然后再调用这个函数就成。当然，由于被调用的函数提供了Docstring，所以需要最后的&lt;code&gt;wrapper.__doc__ = func.__doc__&lt;/code&gt;这句话，把被调函数文档作为装饰器的文档。&lt;/p&gt;</description></item></channel></rss>