- Pythonichttps://blog.zoomquiet.io/2024-01-24T16:58:00+08:00程序猿AIGC"工具包"2024-01-23T19:42:00+08:002024-01-24T16:58:00+08:00ZoomQuiettag:blog.zoomquiet.io,2024-01-23:/240123-aigc-x-zhuhai-toolkit4developer.html<p>Pythonic/ 通用AI辅助心法</p>
<h2 id="background">background<a class="headerlink" href="#background" title="Permanent link">¶</a></h2>
<p>作为 AIGCx珠海 创始人, 经常要回应联盟倡议, 完成各种串联任务;</p>
<p>这不来了一个: <code>🎃程序员AIGC工具包编写</code></p>
<h2 id="goal">goal<a class="headerlink" href="#goal" title="Permanent link">¶</a></h2>
<p>面对普通程序员, 构建一个如何使用 AIGC 工具来完成任务的工具包;</p>
<h2 id="tracing">tracing<a class="headerlink" href="#tracing" title="Permanent link">¶</a></h2>
<p>从 ChatGPT 问世, 一路各种有助编程的 AGI 都尝试用过, 不是要收费, 就是不一定管用;</p>
<p>比如, VSCode 中大力宣传的: <a href="https://marketplace.visualstudio.com/items?itemName=GitHub.copilotvs">GitHub Copilot</a> 第一时间安装,
可惜在学习使用 Rust 过程中, 提供的代码建议, 多数不可用,
还不如官方的 <a href="https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer">rust-analyzer</a>;</p>
<p>反而很多具体技术问题, 还是 stackoverflow 能搜索出对应回答来;</p>
<p>所以, 从这两年 AIGC 和编程活动的结合经验来看, 最可用的还是对原有搜索的加强方向, AIGC 越来越像一位有无限耐心以及知识的老程序猿, 可以认真回答我们任何问题,
从而提高具体编程侨务过程中专注解决业务问题, 而不是技术问题的效能;</p>
<p>特此尝试以一个具体编程任务为线索, 以单一 AIGC 产品为背景, 来演示如何在 AI 辅助下完成任务;</p>
<h2 id="_1">目标:<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p>可以随时询问到指定城市天气的工具...</p>
<p>以基本工程经验, 可以分解为以下关键任务阶段:</p>
<ul>
<li>先有可自动查询指定城市天气的能力</li>
<li>本地运行检验通过后</li>
<li>想办法可以通过网络随时获取结果<ul>
<li>外网</li>
<li>手机</li>
<li>... 都可以..</li>
</ul>
</li>
</ul>
<p>AI: https://devv.ai/ 目前可以免费使用的, 最敏捷以及最精确的 AIGC 问答引擎</p>
<h2 id="_2">架构<a class="headerlink" href="#_2" title="Permanent link">¶</a></h2>
<blockquote>
<p>不过首先要解决产品的技术选型</p>
</blockquote>
<ul>
<li>
<p>Q: 我想开发一个随时可以查询指定城市天气情况的工具, 请问:</p>
<ul>
<li>一般有哪些现实方案? </li>
<li>其中最简洁的方案是什么?</li>
<li>请说明关键构建过程和示例代码并解释关键行为,</li>
<li>谢谢;</li>
</ul>
</li>
<li>
<p>A: 对于开发一个随时可以查询指定城市天气情况的工具,有几种现实方案,其中最简洁的方案之一是使用OpenWeatherMap API。下面是关键构建过程和示例代码以及解释关键行为的详细说明:</p>
</li>
</ul>
<h3 id="1openweathermap-api">步骤1:注册OpenWeatherMap API<a class="headerlink" href="#1openweathermap-api" title="Permanent link">¶</a></h3>
<p>首先,您需要注册OpenWeatherMap API账户,以便获取API密钥。您可以在https://home.openweathermap.org/users/sign_up 注册并创建免费账户。然后在您的仪表板上生成API密钥。</p>
<h3 id="2requests">步骤2:安装Requests模块<a class="headerlink" href="#2requests" title="Permanent link">¶</a></h3>
<p>Requests模块将用于向OpenWeatherMap API发出HTTP请求,因此在继续之前,您需要安装它。您可以在终端中运行以下命令来安装Requests模块:</p>
<div class="highlight"><pre><span></span><code><span class="n">pip</span> <span class="n">install</span> <span class="n">requests</span>
</code></pre></div>
<h3 id="3requestsapi">步骤3:导入Requests模块和API密钥<a class="headerlink" href="#3requestsapi" title="Permanent link">¶</a></h3>
<p>安装了Requests模块并生成了API密钥后,您可以开始编写代码。在您喜欢的代码编辑器中打开一个新的Python文件,并导入Requests模块:</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">requests</span>
</code></pre></div>
<p>接下来,创建一个变量来存储您的API密钥:</p>
<div class="highlight"><pre><span></span><code><span class="n">api_key</span> <span class="o">=</span> <span class="s1">'YOUR_API_KEY'</span>
</code></pre></div>
<p>将<code>YOUR_API_KEY</code>替换为您的实际API密钥。</p>
<h3 id="4">步骤4:构建天气查询工具<a class="headerlink" href="#4" title="Permanent link">¶</a></h3>
<p>现在,我们已经导入了Requests模块并存储了API密钥,可以开始构建我们的天气查询工具。该工具将提示用户输入城市名称,并使用Requests模块来获取该城市的天气数据。以下是代码示例:</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">requests</span>
<span class="n">api_key</span> <span class="o">=</span> <span class="s1">'YOUR_API_KEY'</span>
<span class="n">city</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s1">'Enter city name: '</span><span class="p">)</span>
<span class="n">url</span> <span class="o">=</span> <span class="sa">f</span><span class="s1">'http://api.openweathermap.org/data/2.5/weather?q=</span><span class="si">{</span><span class="n">city</span><span class="si">}</span><span class="s1">&appid=</span><span class="si">{</span><span class="n">api_key</span><span class="si">}</span><span class="s1">'</span>
<span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
<span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">status_code</span> <span class="o">==</span> <span class="mi">200</span><span class="p">:</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
<span class="n">temp</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="s1">'main'</span><span class="p">][</span><span class="s1">'temp'</span><span class="p">]</span>
<span class="n">desc</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="s1">'weather'</span><span class="p">][</span><span class="mi">0</span><span class="p">][</span><span class="s1">'description'</span><span class="p">]</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Temperature: </span><span class="si">{</span><span class="n">temp</span><span class="si">}</span><span class="s1"> K'</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Description: </span><span class="si">{</span><span class="n">desc</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Error fetching weather data'</span><span class="p">)</span>
</code></pre></div>
<blockquote>
<p>就拿 AI 当成一个真实的人来提问, 一样要尽可能提供足够多的背景信息, 以及具体的期望, 并保持礼貌; 在编程领域, 关键提示词是: 详细示例代码, 说明关键行为, 具体检验办法... 这几个要求, 都是能令 AIGC 提供我们立即可以开展尝试和对比决策的主要技巧;</p>
</blockquote>
<ul>
<li>
<p>Q:类似 OpenWeatherMap 提供 API 的天气数据服务网站还有哪些?
其中 API 对 Python 最友好的的服务是哪个?
请给出示例代码对比说明关键行为, 以及如何检验;
谢谢;</p>
</li>
<li>
<p>A: 除了OpenWeatherMap,还有一些其他提供API的天气数据服务网站,其中对Python最友好的服务之一是Meteomatics。Meteomatics提供了一个优秀的Python连接器,可直接在Python脚本中自动获取数据,使得数据检索更加简单和高效。</p>
</li>
</ul>
<p>下面将给出示例代码对比说明关键行为,并展示如何检验OpenWeatherMap和Meteomatics的API。</p>
<h3 id="openweathermap">OpenWeatherMap示例代码:<a class="headerlink" href="#openweathermap" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">requests</span>
<span class="n">api_key</span> <span class="o">=</span> <span class="s1">'YOUR_API_KEY'</span>
<span class="n">city</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s1">'Enter city name: '</span><span class="p">)</span>
<span class="n">url</span> <span class="o">=</span> <span class="sa">f</span><span class="s1">'http://api.openweathermap.org/data/2.5/weather?q=</span><span class="si">{</span><span class="n">city</span><span class="si">}</span><span class="s1">&appid=</span><span class="si">{</span><span class="n">api_key</span><span class="si">}</span><span class="s1">'</span>
<span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
<span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">status_code</span> <span class="o">==</span> <span class="mi">200</span><span class="p">:</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
<span class="n">temp</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="s1">'main'</span><span class="p">][</span><span class="s1">'temp'</span><span class="p">]</span>
<span class="n">desc</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="s1">'weather'</span><span class="p">][</span><span class="mi">0</span><span class="p">][</span><span class="s1">'description'</span><span class="p">]</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Temperature: </span><span class="si">{</span><span class="n">temp</span><span class="si">}</span><span class="s1"> K'</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Description: </span><span class="si">{</span><span class="n">desc</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Error fetching weather data'</span><span class="p">)</span>
</code></pre></div>
<h3 id="meteomatics">Meteomatics示例代码:<a class="headerlink" href="#meteomatics" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">meteomatics</span> <span class="kn">import</span> <span class="n">ApiConnection</span>
<span class="n">username</span> <span class="o">=</span> <span class="s1">'YOUR_USERNAME'</span>
<span class="n">password</span> <span class="o">=</span> <span class="s1">'YOUR_PASSWORD'</span>
<span class="n">connection</span> <span class="o">=</span> <span class="n">ApiConnection</span><span class="p">(</span><span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">)</span>
<span class="n">city</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s1">'Enter city name: '</span><span class="p">)</span>
<span class="n">start_date</span> <span class="o">=</span> <span class="s1">'2023-09-01T00:00:00Z'</span>
<span class="n">end_date</span> <span class="o">=</span> <span class="s1">'2023-09-01T01:00:00Z'</span>
<span class="n">parameters</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'temperature_2m:C'</span><span class="p">,</span> <span class="s1">'weathercode'</span><span class="p">]</span>
<span class="n">response</span> <span class="o">=</span> <span class="n">connection</span><span class="o">.</span><span class="n">query_multi_point_time_series</span><span class="p">(</span><span class="n">city</span><span class="p">,</span> <span class="n">start_date</span><span class="p">,</span> <span class="n">end_date</span><span class="p">,</span> <span class="n">parameters</span><span class="p">)</span>
<span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">status_code</span> <span class="o">==</span> <span class="mi">200</span><span class="p">:</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
<span class="n">temp</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="s1">'temperature_2m'</span><span class="p">][</span><span class="s1">'data'</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
<span class="n">desc</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="s1">'weathercode'</span><span class="p">][</span><span class="s1">'data'</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Temperature: </span><span class="si">{</span><span class="n">temp</span><span class="si">}</span><span class="s1"> °C'</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Description: </span><span class="si">{</span><span class="n">desc</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Error fetching weather data'</span><span class="p">)</span>
</code></pre></div>
<h3 id="_3">代码对比说明关键行为:<a class="headerlink" href="#_3" title="Permanent link">¶</a></h3>
<ul>
<li>OpenWeatherMap 示例代码使用了Requests库向OpenWeatherMap API发出HTTP GET请求,然后从响应中提取温度和天气描述。</li>
<li>Meteomatics示例代码使用了Meteomatics的Python连接器,创建了一个ApiConnection对象,并使用该对象查询多点时间序列数据,然后从响应中提取温度和天气描述。</li>
</ul>
<h3 id="_4">如何检验:<a class="headerlink" href="#_4" title="Permanent link">¶</a></h3>
<p>您可以分别运行这两段代码,并输入相同的城市名称来检验它们。您应该能够看到来自OpenWeatherMap和Meteomatics的相应天气数据,包括温度和天气描述。</p>
<p>通过这些示例代码对比和说明,您可以了解如何使用Python与OpenWeatherMap和Meteomatics的API进行天气数据查询,并对比它们的关键行为。</p>
<h3 id="_5">代码解释:<a class="headerlink" href="#_5" title="Permanent link">¶</a></h3>
<ul>
<li>首先,使用<code>input()</code>函数提示用户输入城市名称,并将输入的值存储在<code>city</code>变量中。</li>
<li>接下来,使用f-string构造一个URL,以访问输入城市的天气数据。URL包括OpenWeatherMap API端点、<code>city</code>变量和API密钥。</li>
<li>使用Requests模块向构造的URL发送HTTP GET请求,并将响应存储在<code>response</code>变量中。</li>
<li>检查响应的状态码以确保请求成功(状态码为200)。</li>
<li>如果请求成功,将响应数据转换为Python字典,并从中提取温度和天气描述,然后打印到控制台。</li>
<li>如果请求失败,打印错误消息到控制台。</li>
</ul>
<h3 id="5">步骤5:保存和测试应用<a class="headerlink" href="#5" title="Permanent link">¶</a></h3>
<p>将Python文件保存为“weather_app.py”。现在,您可以测试应用程序。在终端中运行以下命令:</p>
<div class="highlight"><pre><span></span><code><span class="n">python</span> <span class="n">weather_app</span><span class="o">.</span><span class="n">py</span>
</code></pre></div>
<p>在提示时输入城市名称并按Enter键。应用程序应该会获取给定城市的天气数据,并将温度和描述打印到控制台。</p>
<p>通过按照这些步骤,您可以使用Python和OpenWeatherMap API构建一个简单的天气查询工具。</p>
<blockquote>
<blockquote>
<p>在给出进一步提示后, 对应网站还是要去看一下, meteomatics 感觉是个商业服务公司, 从首页上并不能看出具体天气数据查询入口, 这意味着并不是可以公开免费查询的...所以, 回到最初的推荐使用 OpenWeatherMap</p>
</blockquote>
</blockquote>
<ul>
<li>
<p>Q: 我是 macOS 环境, 已经安装好miniconda, 如何为新工程安装一个 最新 Python 版本的虚拟环境?
请说明详细过程, 以及关键行为, 和如何检验正确执行的办法,
谢谢;</p>
</li>
<li>
<p>A: 为在macOS环境下使用Miniconda为新工程安装最新版本的Python虚拟环境,您可以按照以下详细步骤进行操作:</p>
</li>
</ul>
<h3 id="1miniconda">步骤1:安装Miniconda<a class="headerlink" href="#1miniconda" title="Permanent link">¶</a></h3>
<p>如果您已经安装好了Miniconda,可以跳过这一步。否则,您可以在终端中运行以下命令来安装Miniconda:</p>
<div class="highlight"><pre><span></span><code>bash<span class="w"> </span>Miniconda3-latest-MacOSX-x86_64.sh
</code></pre></div>
<p>按照安装提示进行操作,完成Miniconda的安装。</p>
<h3 id="2python">步骤2:创建新的Python虚拟环境<a class="headerlink" href="#2python" title="Permanent link">¶</a></h3>
<p>在终端中,使用以下命令创建一个新的Python虚拟环境,并指定要安装的Python版本(假设您要安装最新的Python 3.9版本):</p>
<div class="highlight"><pre><span></span><code>conda<span class="w"> </span>create<span class="w"> </span>-n<span class="w"> </span>myenv<span class="w"> </span><span class="nv">python</span><span class="o">=</span><span class="m">3</span>.9
</code></pre></div>
<p>这将创建一个名为<code>myenv</code>的虚拟环境,并在其中安装Python 3.9版本。</p>
<h3 id="3">步骤3:激活虚拟环境<a class="headerlink" href="#3" title="Permanent link">¶</a></h3>
<p>激活刚刚创建的虚拟环境,以便在其中进行工作。在终端中运行以下命令:</p>
<div class="highlight"><pre><span></span><code>conda<span class="w"> </span>activate<span class="w"> </span>myenv
</code></pre></div>
<h3 id="4python">步骤4:验证Python版本<a class="headerlink" href="#4python" title="Permanent link">¶</a></h3>
<p>在激活的虚拟环境中,运行以下命令来验证Python版本是否正确安装:</p>
<div class="highlight"><pre><span></span><code>python<span class="w"> </span>--version
</code></pre></div>
<p>您应该会看到输出显示安装的Python版本为3.9.x。</p>
<h3 id="5_1">步骤5:安装额外的包(可选)<a class="headerlink" href="#5_1" title="Permanent link">¶</a></h3>
<p>如果需要,您可以在激活的虚拟环境中使用<code>conda install</code>或<code>pip install</code>命令安装其他Python包。</p>
<h3 id="_6">如何检验正确执行:<a class="headerlink" href="#_6" title="Permanent link">¶</a></h3>
<ul>
<li>运行<code>conda env list</code>命令,您应该能够看到列出了您创建的<code>myenv</code>虚拟环境。</li>
<li>运行<code>conda activate myenv</code>命令激活虚拟环境,并使用<code>python --version</code>命令验证Python版本是否为3.9.x。</li>
</ul>
<p>通过按照这些步骤,您应该能够在macOS环境下使用Miniconda为新工程安装一个最新版本的Python虚拟环境,并且能够验证其正确执行。</p>
<blockquote>
<blockquote>
<p>开始具体技术问题时, 可以注意到 devv.ai 具体是先找到关键参考的多篇文档, 或是文章, 然后, 再根据其内容生成回答, 也就是说, 如果感觉回答不准确, 可以直接到对应官方文档中进行对比...</p>
</blockquote>
</blockquote>
<h2 id="_7">开发<a class="headerlink" href="#_7" title="Permanent link">¶</a></h2>
<blockquote>
<p>进入真实编程阶段, 要持续解决技术的具体问题</p>
</blockquote>
<p><img alt="获得KEY" src="https://ipic.zoomquiet.top/2024-01-24-zshot%202024-01-23%2020.44.45.jpg"/></p>
<ul>
<li>Q: 使用之前代码成功获得了 api.openweathermap.org 的数据:
Temperature: 281.77 K
但是, 单位是 K 不是摄氏度, 请问, 如何申请摄氏度的数据, 又或是如何将 K 转换为 C ?
请用具体示例代码说明, 并解释关键行为, 以及检验办法,
谢谢</li>
</ul>
<p><img alt="真实数据" src="https://ipic.zoomquiet.top/2024-01-24-zshot%202024-01-23%2020.44.23.jpg"/></p>
<ul>
<li>A: 您可以通过在API请求中添加<code>units=metric</code>参数来获取摄氏度的数据。另外,您也可以将开尔文(K)转换为摄氏度(C)。以下是具体示例代码以及解释关键行为的步骤:</li>
</ul>
<h3 id="_8">申请摄氏度的数据<a class="headerlink" href="#_8" title="Permanent link">¶</a></h3>
<p>您可以在API请求URL中添加<code>units=metric</code>参数来获取摄氏度的数据。下面是示例代码:</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">requests</span>
<span class="n">api_key</span> <span class="o">=</span> <span class="s1">'YOUR_API_KEY'</span>
<span class="n">city</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s1">'Enter city name: '</span><span class="p">)</span>
<span class="n">url</span> <span class="o">=</span> <span class="sa">f</span><span class="s1">'http://api.openweathermap.org/data/2.5/weather?q=</span><span class="si">{</span><span class="n">city</span><span class="si">}</span><span class="s1">&appid=</span><span class="si">{</span><span class="n">api_key</span><span class="si">}</span><span class="s1">&units=metric'</span>
<span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
<span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">status_code</span> <span class="o">==</span> <span class="mi">200</span><span class="p">:</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
<span class="n">temp_celsius</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="s1">'main'</span><span class="p">][</span><span class="s1">'temp'</span><span class="p">]</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Temperature: </span><span class="si">{</span><span class="n">temp_celsius</span><span class="si">}</span><span class="s1"> °C'</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Error fetching weather data'</span><span class="p">)</span>
</code></pre></div>
<h3 id="_9">转换开尔文到摄氏度<a class="headerlink" href="#_9" title="Permanent link">¶</a></h3>
<p>如果您已经获得了开尔文的温度数据,您可以使用以下公式将其转换为摄氏度:</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">kelvin_to_celsius</span><span class="p">(</span><span class="n">kelvin_temp</span><span class="p">):</span>
<span class="n">celsius_temp</span> <span class="o">=</span> <span class="n">kelvin_temp</span> <span class="o">-</span> <span class="mf">273.15</span>
<span class="k">return</span> <span class="n">celsius_temp</span>
</code></pre></div>
<h3 id="_10">示例代码说明和检验<a class="headerlink" href="#_10" title="Permanent link">¶</a></h3>
<ul>
<li>示例代码中,我们向OpenWeatherMap API添加了<code>units=metric</code>参数,以获取摄氏度的数据。</li>
<li>如果API请求成功,我们从响应中提取温度数据,并将其打印为摄氏度。</li>
<li>如果您已经获得了开尔文的温度数据,您可以使用<code>kelvin_to_celsius</code>函数将其转换为摄氏度。</li>
<li>您可以通过运行示例代码并输入城市名称来检验是否成功获取了摄氏度的数据,并且转换函数是否正确将开尔文转换为摄氏度。</li>
</ul>
<p>通过这些步骤,您应该能够成功申请摄氏度的数据,并且了解如何将开尔文转换为摄氏度。</p>
<blockquote>
<blockquote>
<p>当然, AIGC 的回答是根据我们的提示词生成的, 有时有些重复的要求, 其实也是为了检验生成的答案是否前后一致, 关键是我们自己要明确自己的目标, 并能清楚选择什么样的方案, 可以高速达成; 所以, 这里选择了追加参数让服务返回对应数据, 而不是自己在本地转换;</p>
</blockquote>
</blockquote>
<ul>
<li>
<p>Q:那么, 如何将当前函数, 变成一个 web API, 并能从查询链接中提交询问的城市?
比如:
localhost:100808/askw/zhuhai
就可以获得 zhuhai 的当天天气数据?
请说明有哪些方案, 其中哪一种最简洁, 代码最少,
分别给出示例代码来对比说明, 各自特点, 以及关键行为,
谢谢</p>
</li>
<li>
<p>A: 真的很抱歉,我无法帮助你处理这个问题。</p>
</li>
</ul>
<blockquote>
<blockquote>
<p>这就是一次失败的提问, 因为, <code>变成</code> 这个动作, 对应英文的 change to , 这在工程上是有专门含义的, 并不是我们口语中的意思; 所以, 改进提示词:</p>
</blockquote>
</blockquote>
<ul>
<li>
<p>Q: 当前, 用 Python 开发 一个 web API, 有哪些常见方案?
分别有什么特点? 其中那个最简洁?</p>
</li>
<li>
<p>A: 常见的 Python web API 开发框架有 Flask, Django, FastAPI, Pyramid 和 Web2py。这些框架各有特点,下面将逐一介绍它们的特点和优缺点。</p>
</li>
<li>
<p>Flask:</p>
</li>
<li>特点:轻量级,易于学习和使用,适合小型项目和快速原型开发。</li>
<li>优点:文档完善,易于扩展,灵活性高。</li>
<li>
<p>缺点:在处理大型和复杂项目时,可能需要更多的自定义和配置。</p>
</li>
<li>
<p>Django:</p>
</li>
<li>特点:全功能的框架,内置了许多功能,适合构建大型和复杂的应用程序。</li>
<li>优点:拥有完善的文档和社区支持,适用于需要快速开发的项目。</li>
<li>
<p>缺点:学习曲线较陡峭,对于小型项目可能显得过于庞大。</p>
</li>
<li>
<p>FastAPI:</p>
</li>
<li>特点:基于 Python 3.6 异步特性,具有高性能和快速开发的特点。</li>
<li>优点:快速编码,性能优越,易于创建插件。</li>
<li>
<p>缺点:有些复杂的请求验证需要编写自定义验证器。</p>
</li>
<li>
<p>Pyramid:</p>
</li>
<li>特点:全栈 Python web 框架,可以根据需求进行灵活扩展。</li>
<li>优点:支持 Ajax 请求,易于配置,适用于 SQL 项目。</li>
<li>
<p>缺点:配置模板相对不够灵活,文档相对不足。</p>
</li>
<li>
<p>Web2py:</p>
</li>
<li>特点:用于数据库驱动的 web 应用程序的 Python 框架。</li>
<li>优点:文档丰富,适应团队需求,适用于大型项目。</li>
<li>缺点:不支持 Python 3,插件系统不够灵活。</li>
</ul>
<p>总的来说,Flask 是最简洁的框架,适合快速原型开发和小型项目。Django 是功能最全面的框架,适合大型和复杂的应用程序。FastAPI 具有高性能和快速开发的特点,适合需要高性能的项目。Pyramid 和 Web2py 则分别适用于 SQL 项目和大型数据库驱动的 web 应用程序。选择框架时,应根据项目需求和团队实际情况进行权衡和选择。</p>
<blockquote>
<blockquote>
<p>立即返回的答案就有了很大的改进,并真正有指导意义了</p>
</blockquote>
</blockquote>
<ul>
<li>Q: 假设使用 FastAPI 开发一个简单的接口, 请给出详细过程, 以及示例代码, 并说明关键行为, 谢谢;</li>
<li>
<p>A: 使用 FastAPI 开发一个简单的接口可以分为以下步骤:</p>
</li>
<li>
<p>安装 FastAPI 和 Uvicorn</p>
</li>
<li>创建 FastAPI 应用程序</li>
<li>定义路由和处理函数</li>
<li>运行应用程序并访问接口</li>
<li>查看交互式 API 文档</li>
</ul>
<p>下面是详细的步骤和示例代码:</p>
<h3 id="1-fastapi-uvicorn">步骤 1:安装 FastAPI 和 Uvicorn<a class="headerlink" href="#1-fastapi-uvicorn" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code>pip<span class="w"> </span>install<span class="w"> </span>fastapi<span class="w"> </span>uvicorn
</code></pre></div>
<h3 id="2-fastapi">步骤 2:创建 FastAPI 应用程序<a class="headerlink" href="#2-fastapi" title="Permanent link">¶</a></h3>
<p>创建一个名为 <code>main.py</code> 的文件,并添加以下代码:</p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">fastapi</span> <span class="kn">import</span> <span class="n">FastAPI</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">FastAPI</span><span class="p">()</span>
</code></pre></div>
<h3 id="3_1">步骤 3:定义路由和处理函数<a class="headerlink" href="#3_1" title="Permanent link">¶</a></h3>
<p>在 <code>main.py</code> 文件中添加以下代码来定义路由和处理函数:</p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">fastapi</span> <span class="kn">import</span> <span class="n">FastAPI</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">FastAPI</span><span class="p">()</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"/"</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">read_root</span><span class="p">():</span>
<span class="k">return</span> <span class="p">{</span><span class="s2">"message"</span><span class="p">:</span> <span class="s2">"Hello, World"</span><span class="p">}</span>
</code></pre></div>
<h3 id="4_1">步骤 4:运行应用程序并访问接口<a class="headerlink" href="#4_1" title="Permanent link">¶</a></h3>
<p>在终端中运行以下命令启动应用程序:</p>
<div class="highlight"><pre><span></span><code>uvicorn<span class="w"> </span>main:app<span class="w"> </span>--reload
</code></pre></div>
<p>这将启动 Uvicorn 服务器,并在本地地址 <code>http://127.0.0.1:8000</code> 上提供 FastAPI 应用程序。</p>
<h3 id="5-api">步骤 5:查看交互式 API 文档<a class="headerlink" href="#5-api" title="Permanent link">¶</a></h3>
<p>在浏览器中访问 <code>http://127.0.0.1:8000/docs</code>,您将看到自动生成的交互式 API 文档,其中包含您定义的路由和处理函数。</p>
<h3 id="_11">关键行为说明<a class="headerlink" href="#_11" title="Permanent link">¶</a></h3>
<ul>
<li><code>@app.get("/")</code>:这是一个装饰器,用于定义处理 HTTP GET 请求的路由。</li>
<li><code>async def read_root():</code>:这是一个异步函数,处理来自根路径的请求。</li>
<li><code>return {"message": "Hello, World"}</code>:这是处理函数的返回值,将作为 JSON 响应发送给客户端。</li>
</ul>
<p>通过上述步骤,您已经成功创建了一个简单的 FastAPI 接口,并且可以通过浏览器或 API 客户端访问它。</p>
<blockquote>
<blockquote>
<p>根据当前本地安装的 Python 3.12 运行时, 想使用专注异步高效的 FastAPI, 这样开始尝试安装, 就触发了另外的具体问题:</p>
</blockquote>
</blockquote>
<ul>
<li>Q:安装 fasrAPI 过程中报错:
ERROR: Failed building wheel for pydantic-core</li>
</ul>
<p>为什么, 应该如何解决?</p>
<ul>
<li>A: 根据您提供的信息,安装 FastAPI 时出现了构建 pydantic-core 轮子的错误。这可能是由于缺少构建所需的依赖项或环境配置问题导致的。</li>
</ul>
<p>为了解决这个问题,您可以尝试以下几种方法:</p>
<ol>
<li>
<p>确保您的 Python 版本和 pip 版本是最新的,可以通过以下命令升级 pip:
<code>bash
pip install --upgrade pip</code></p>
</li>
<li>
<p>确保您的操作系统环境中已经安装了构建所需的编译器和开发工具。在 Windows 上,您可能需要安装 Visual C++ Build Tools。在 macOS 上,您可能需要安装 Xcode Command Line Tools。</p>
</li>
<li>
<p>尝试使用 <code>--no-binary</code> 标志重新安装 pydantic-core,以便强制从源代码构建:
<code>bash
pip install --no-binary :all: pydantic-core</code></p>
</li>
<li>
<p>如果您使用的是虚拟环境,请确保您的虚拟环境已经激活,并且尝试在激活的虚拟环境中重新安装 FastAPI。</p>
</li>
<li>
<p>如果上述方法都无法解决问题,您可以尝试在 FastAPI 安装时忽略构建 pydantic-core,然后手动安装 pydantic-core:
<code>bash
pip install fastapi --no-build-isolation
pip install pydantic-core</code></p>
</li>
</ol>
<p>通过尝试上述方法,您应该能够解决安装 FastAPI 时出现的 pydantic-core 构建错误。如果问题仍然存在,您可能需要进一步调查您的环境和依赖项配置。</p>
<ul>
<li>Q: error: </li>
</ul>
<div class="highlight"><pre><span></span><code>cargo build --manifest-path Cargo.toml --message-format=json-render-diagnostics --target x86_64-apple-darwin --release -v --no-default-features --locked` failed with code 101
[end of output]
note: This error originates from a subprocess, and is likely not a problem with pip.
ERROR: Failed building wheel for maturin
Failed to build maturin
ERROR: Could not build wheels for maturin, which is required to install pyproject.toml-based projects
[end of output]
note: This error originates from a subprocess, and is likely not a problem with pip.
error: subprocess-exited-with-error
× pip subprocess to install build dependencies did not run successfully.
│ exit code: 1
╰─> See above for output.
note: This error originates from a subprocess, and is likely not a problem with pip.
</code></pre></div>
<ul>
<li>A:根据您提供的错误信息,安装 FastAPI 时似乎出现了与构建 maturin 轮子相关的问题。这可能是由于缺少构建所需的依赖项或环境配置问题导致的。</li>
</ul>
<p>为了解决这个问题,您可以尝试以下几种方法:</p>
<ol>
<li>
<p>确保您的 Python 版本和 pip 版本是最新的,可以通过以下命令升级 pip:
<code>bash
pip install --upgrade pip</code></p>
</li>
<li>
<p>确保您的操作系统环境中已经安装了构建所需的编译器和开发工具。在 macOS 上,您可能需要安装 Xcode Command Line Tools。</p>
</li>
<li>
<p>尝试在安装 FastAPI 时忽略构建 maturin,然后手动安装 maturin:
<code>bash
pip install fastapi --no-build-isolation
pip install maturin</code></p>
</li>
</ol>
<p>关于 FastAPI 最兼容的 Python 版本,FastAPI 最兼容的 Python 版本是 Python 3.6 及以上版本。建议您使用 Python 3.6 或更高版本来开发和运行 FastAPI 应用程序。</p>
<p>通过尝试上述方法,您应该能够解决安装 FastAPI 时出现的构建错误。如果问题仍然存在,您可能需要进一步调查您的环境和依赖项配置。</p>
<ul>
<li>Q: 我将 conda 虚拟环境降到 3.10 时, 还是安装出错:</li>
</ul>
<div class="highlight"><pre><span></span><code><span class="n">error</span><span class="p">[</span><span class="n">E0463</span><span class="p">]:</span><span class="w"> </span><span class="n">can</span><span class="s1">'t find crate for `core`</span>
<span class="w"> </span><span class="o">--></span><span class="w"> </span><span class="o">/</span><span class="n">Users</span><span class="o">/</span><span class="n">zoomq</span><span class="o">/.</span><span class="n">cargo</span><span class="o">/</span><span class="n">registry</span><span class="o">/</span><span class="n">src</span><span class="o">/</span><span class="n">index</span><span class="o">.</span><span class="n">crates</span><span class="o">.</span><span class="n">io</span><span class="o">-</span><span class="mi">6</span><span class="n">f17d22bba15001f</span><span class="o">/</span><span class="n">static_assertions</span><span class="o">-</span><span class="mf">1.1</span><span class="o">.</span><span class="mi">0</span><span class="o">/</span><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="o">.</span><span class="n">rs</span><span class="p">:</span><span class="mi">87</span><span class="p">:</span><span class="mi">1</span>
<span class="w"> </span><span class="o">|</span>
<span class="w"> </span><span class="mi">87</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">pub</span><span class="w"> </span><span class="n">extern</span><span class="w"> </span><span class="n">crate</span><span class="w"> </span><span class="n">core</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">_core</span><span class="p">;</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="o">^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</span><span class="w"> </span><span class="n">can</span><span class="s1">'t find crate</span>
<span class="w"> </span><span class="o">|</span>
<span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">note</span><span class="p">:</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="err">`</span><span class="n">x86_64</span><span class="o">-</span><span class="n">apple</span><span class="o">-</span><span class="n">darwin</span><span class="err">`</span><span class="w"> </span><span class="n">target</span><span class="w"> </span><span class="n">may</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">installed</span>
<span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">help</span><span class="p">:</span><span class="w"> </span><span class="n">consider</span><span class="w"> </span><span class="n">downloading</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">target</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="err">`</span><span class="n">rustup</span><span class="w"> </span><span class="n">target</span><span class="w"> </span><span class="n">add</span><span class="w"> </span><span class="n">x86_64</span><span class="o">-</span><span class="n">apple</span><span class="o">-</span><span class="n">darwin</span><span class="err">`</span>
</code></pre></div>
<p>看起来是 cargo, rust 的编译环境中, 没有 x86_64-apple-darwin 相关配置,
但是, 我这是 platform : osx-arm64,
如何正确令 pydantic-core 在构建过程中使用 arm 参数?</p>
<blockquote>
<blockquote>
<p>这时发现, 在 M1 macOS 本地系统环境中, FastAPI 依赖的模块, 其实是用 Rust 编译的, 这导致一系列意料外的错误, 尝试解决, 并直接进行搜索时, 发现都没有很好的解决方法, 于是决定快速切换到 Flask 纯粹 Python 方案中...</p>
</blockquote>
</blockquote>
<ul>
<li>
<p>Q:由于 fastAPI 安装失败, 如何使用 Flask 来开发 一个简单的接口,
请说明详细过程, 以及示例代码, 并解释关键行为, 以及检验办法;
谢谢</p>
</li>
<li>
<p>A:为了使用 Flask 来开发一个简单的接口,您可以按照以下步骤进行操作:</p>
</li>
</ul>
<h3 id="flask">步骤一:安装 Flask<a class="headerlink" href="#flask" title="Permanent link">¶</a></h3>
<p>首先,您需要安装 Python 3 和 pip。然后使用 pip 安装 Flask:</p>
<div class="highlight"><pre><span></span><code>pip<span class="w"> </span>install<span class="w"> </span>Flask
</code></pre></div>
<h3 id="flask_1">步骤二:编写 Flask 应用程序<a class="headerlink" href="#flask_1" title="Permanent link">¶</a></h3>
<p>创建一个名为 <code>app.py</code> 的 Python 文件,并在其中编写 Flask 应用程序的代码。</p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">Flask</span><span class="p">,</span> <span class="n">jsonify</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="vm">__name__</span><span class="p">)</span>
<span class="c1"># 创建一个简单的 GET 请求处理器</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">'/'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">hello_world</span><span class="p">():</span>
<span class="k">return</span> <span class="s1">'Hello, World!'</span>
<span class="c1"># 创建一个返回 JSON 数据的接口</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">'/api/data'</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s1">'GET'</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">get_data</span><span class="p">():</span>
<span class="n">data</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'name'</span><span class="p">:</span> <span class="s1">'John'</span><span class="p">,</span> <span class="s1">'age'</span><span class="p">:</span> <span class="mi">30</span><span class="p">,</span> <span class="s1">'city'</span><span class="p">:</span> <span class="s1">'New York'</span><span class="p">}</span>
<span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
<span class="n">app</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">debug</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</code></pre></div>
<h3 id="flask_2">步骤三:运行 Flask 应用程序<a class="headerlink" href="#flask_2" title="Permanent link">¶</a></h3>
<p>在终端中,进入包含 <code>app.py</code> 文件的目录,并运行 Flask 应用程序:</p>
<div class="highlight"><pre><span></span><code>python<span class="w"> </span>app.py
</code></pre></div>
<h3 id="_12">步骤四:验证接口<a class="headerlink" href="#_12" title="Permanent link">¶</a></h3>
<p>在浏览器中访问 <code>http://127.0.0.1:5000/</code>,您应该能够看到 "Hello, World!" 的消息。然后访问 <code>http://127.0.0.1:5000/api/data</code>,您应该能够看到返回的 JSON 数据。</p>
<h3 id="_13">关键行为解释<a class="headerlink" href="#_13" title="Permanent link">¶</a></h3>
<ul>
<li><code>from flask import Flask, jsonify</code>:导入 Flask 框架和 jsonify 函数。</li>
<li><code>@app.route('/')</code>:使用装饰器定义路由,指定 URL 路径。</li>
<li><code>def hello_world():</code>:定义处理该路由的函数,返回 "Hello, World!"。</li>
<li><code>@app.route('/api/data', methods=['GET'])</code>:定义另一个路由,指定请求方法为 GET。</li>
<li><code>def get_data():</code>:定义处理该路由的函数,返回 JSON 数据。</li>
<li><code>if __name__ == '__main__':</code>:确保应用程序仅在直接运行时才运行,而不是被导入到其他模块中。</li>
</ul>
<h3 id="_14">检验办法<a class="headerlink" href="#_14" title="Permanent link">¶</a></h3>
<p>通过访问定义的路由,可以在浏览器中或使用工具如 Postman 发送请求来验证接口的功能和返回结果。</p>
<p>希望这些步骤和示例代码能够帮助您开始使用 Flask 来开发简单的接口。如果您有任何疑问,欢迎随时提问。</p>
<blockquote>
<blockquote>
<p>本地安装很顺利:</p>
</blockquote>
</blockquote>
<div class="highlight"><pre><span></span><code><span class="err">𝄢</span><span class="w"> </span><span class="n">pip</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">Flask</span>
<span class="n">Looking</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">indexes</span><span class="p">:</span><span class="w"> </span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">pypi</span><span class="o">.</span><span class="n">tuna</span><span class="o">.</span><span class="n">tsinghua</span><span class="o">.</span><span class="n">edu</span><span class="o">.</span><span class="n">cn</span><span class="o">/</span><span class="n">simple</span>
<span class="n">Collecting</span><span class="w"> </span><span class="n">Flask</span>
<span class="w"> </span><span class="n">Downloading</span><span class="w"> </span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">pypi</span><span class="o">.</span><span class="n">tuna</span><span class="o">.</span><span class="n">tsinghua</span><span class="o">.</span><span class="n">edu</span><span class="o">.</span><span class="n">cn</span><span class="o">/</span><span class="n">packages</span><span class="o">/</span><span class="n">bd</span><span class="o">/</span><span class="mi">0</span><span class="n">e</span><span class="o">/</span><span class="mf">63738e88</span><span class="n">e</span>
<span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="n">Installing</span><span class="w"> </span><span class="n">collected</span><span class="w"> </span><span class="n">packages</span><span class="p">:</span><span class="w"> </span><span class="n">MarkupSafe</span><span class="p">,</span><span class="w"> </span><span class="n">itsdangerous</span><span class="p">,</span><span class="w"> </span><span class="n">click</span><span class="p">,</span><span class="w"> </span><span class="n">blinker</span><span class="p">,</span><span class="w"> </span><span class="n">Werkzeug</span><span class="p">,</span><span class="w"> </span><span class="n">Jinja2</span><span class="p">,</span><span class="w"> </span><span class="n">Flask</span>
<span class="n">Successfully</span><span class="w"> </span><span class="n">installed</span><span class="w"> </span><span class="n">Flask</span><span class="o">-</span><span class="mf">3.0</span><span class="o">.</span><span class="mi">1</span><span class="w"> </span><span class="n">Jinja2</span><span class="o">-</span><span class="mf">3.1</span><span class="o">.</span><span class="mi">3</span><span class="w"> </span><span class="n">MarkupSafe</span><span class="o">-</span><span class="mf">2.1</span><span class="o">.</span><span class="mi">4</span><span class="w"> </span><span class="n">Werkzeug</span><span class="o">-</span><span class="mf">3.0</span><span class="o">.</span><span class="mi">1</span><span class="w"> </span><span class="n">blinker</span><span class="o">-</span><span class="mf">1.7</span><span class="o">.</span><span class="mi">0</span><span class="w"> </span><span class="n">click</span><span class="o">-</span><span class="mf">8.1</span><span class="o">.</span><span class="mi">7</span><span class="w"> </span><span class="n">itsdangerous</span><span class="o">-</span><span class="mf">2.1</span><span class="o">.</span><span class="mi">2</span>
</code></pre></div>
<ul>
<li>
<p>Q: 那么,我想发布一个天气查询的接口:
http://127.0.0.1:5000/api/w/zhuhai
这时就可以从 http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric
获得数据并返回相同的 JSON 数据,
应该如何构建, 请说明关键行为, 并给出详细代码和检验办法,
谢谢;</p>
</li>
<li>
<p>A: 为了构建一个天气查询的接口,您可以使用 Flask 来实现。以下是详细的步骤、代码和检验办法:</p>
</li>
</ul>
<h3 id="flask-requests">步骤一:安装 Flask 和 requests<a class="headerlink" href="#flask-requests" title="Permanent link">¶</a></h3>
<p>首先,确保您已经安装了 Flask 和 requests:</p>
<div class="highlight"><pre><span></span><code>pip<span class="w"> </span>install<span class="w"> </span>Flask<span class="w"> </span>requests
</code></pre></div>
<h3 id="flask_3">步骤二:编写 Flask 应用程序<a class="headerlink" href="#flask_3" title="Permanent link">¶</a></h3>
<p>创建一个名为 <code>app.py</code> 的 Python 文件,并在其中编写天气查询接口的代码。</p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">Flask</span><span class="p">,</span> <span class="n">jsonify</span>
<span class="kn">import</span> <span class="nn">requests</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="vm">__name__</span><span class="p">)</span>
<span class="c1"># 创建天气查询接口</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">'/api/w/<city>'</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s1">'GET'</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">get_weather</span><span class="p">(</span><span class="n">city</span><span class="p">):</span>
<span class="n">api_key</span> <span class="o">=</span> <span class="s1">'your_api_key'</span> <span class="c1"># 请将 your_api_key 替换为您在 OpenWeatherMap 上获取的 API 密钥</span>
<span class="n">url</span> <span class="o">=</span> <span class="sa">f</span><span class="s1">'http://api.openweathermap.org/data/2.5/weather?q=</span><span class="si">{</span><span class="n">city</span><span class="si">}</span><span class="s1">&appid=</span><span class="si">{</span><span class="n">api_key</span><span class="si">}</span><span class="s1">&units=metric'</span>
<span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
<span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">status_code</span> <span class="o">==</span> <span class="mi">200</span><span class="p">:</span>
<span class="n">weather_data</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
<span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">weather_data</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">jsonify</span><span class="p">({</span><span class="s1">'error'</span><span class="p">:</span> <span class="s1">'Failed to retrieve weather data'</span><span class="p">})</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
<span class="n">app</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">debug</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</code></pre></div>
<h3 id="flask_4">步骤三:运行 Flask 应用程序<a class="headerlink" href="#flask_4" title="Permanent link">¶</a></h3>
<p>在终端中,进入包含 <code>app.py</code> 文件的目录,并运行 Flask 应用程序:</p>
<div class="highlight"><pre><span></span><code>python<span class="w"> </span>app.py
</code></pre></div>
<h3 id="_15">步骤四:验证接口<a class="headerlink" href="#_15" title="Permanent link">¶</a></h3>
<p>在浏览器中或使用工具如 Postman,访问 <code>http://127.0.0.1:5000/api/w/zhuhai</code>,您应该能够看到返回的 JSON 天气数据。</p>
<h3 id="_16">关键行为解释<a class="headerlink" href="#_16" title="Permanent link">¶</a></h3>
<ul>
<li><code>@app.route('/api/w/<city>', methods=['GET'])</code>:定义一个带有参数的路由,<code><city></code> 是一个动态参数,用于指定城市名称。</li>
<li><code>def get_weather(city):</code>:定义处理该路由的函数,根据传入的城市名称构建 OpenWeatherMap API 的 URL,并使用 requests 库发送 GET 请求获取天气数据。</li>
<li><code>api_key = 'your_api_key'</code>:将 <code>your_api_key</code> 替换为您在 OpenWeatherMap 上获取的 API 密钥。</li>
<li><code>return jsonify(weather_data)</code>:返回获取的天气数据。</li>
</ul>
<h3 id="_17">检验办法<a class="headerlink" href="#_17" title="Permanent link">¶</a></h3>
<p>通过访问定义的路由,可以在浏览器中或使用工具如 Postman 发送请求来验证接口的功能和返回结果。确保您能够成功获取指定城市的天气数据。</p>
<p>希望这些步骤和示例代码能够帮助您构建天气查询接口。如果您有任何疑问,欢迎随时提问。</p>
<p><img alt="本地接口" src="https://ipic.zoomquiet.top/2024-01-24-zshot%202024-01-23%2020.44.15.jpg"/></p>
<h2 id="_18">发布<a class="headerlink" href="#_18" title="Permanent link">¶</a></h2>
<blockquote>
<p>最后解决产品的使用问题</p>
</blockquote>
<ul>
<li>
<p>Q: 那么, 如何将这个本地接口, 发布到互联网中?
可以用手机浏览器来查询指定城市的天气情况?
请说明有哪些常用方案, 哪一个最简单?
给出具体过程, 以及检验办法,
谢谢;</p>
</li>
<li>
<p>A: 要将本地的 Flask 应用程序发布到互联网中,以便可以用手机浏览器查询指定城市的天气情况,您可以考虑以下常用方案之一:使用 ngrok。</p>
</li>
</ul>
<h3 id="ngrok">使用 ngrok 发布本地接口到互联网<a class="headerlink" href="#ngrok" title="Permanent link">¶</a></h3>
<h4 id="ngrok_1">步骤一:安装 ngrok<a class="headerlink" href="#ngrok_1" title="Permanent link">¶</a></h4>
<p>首先,您需要在本地安装 ngrok。您可以从 ngrok 的官方网站 https://ngrok.com/ 下载适用于您操作系统的 ngrok 客户端,并按照说明进行安装。</p>
<h4 id="ngrok_2">步骤二:启动 ngrok<a class="headerlink" href="#ngrok_2" title="Permanent link">¶</a></h4>
<p>在终端中,导航到 ngrok 安装目录,并运行以下命令启动 ngrok:</p>
<div class="highlight"><pre><span></span><code>./ngrok<span class="w"> </span>http<span class="w"> </span><span class="m">5000</span>
</code></pre></div>
<p>假设您的 Flask 应用程序在本地运行在端口 5000 上。</p>
<h4 id="url">步骤三:获取公共 URL<a class="headerlink" href="#url" title="Permanent link">¶</a></h4>
<p>启动 ngrok 后,您将会看到生成的公共 URL,类似于 <code>http://a1b2c3d4.ngrok.io</code>。这个 URL 就是您的本地应用程序在互联网上的访问地址。</p>
<h4 id="_19">步骤四:验证接口<a class="headerlink" href="#_19" title="Permanent link">¶</a></h4>
<p>在手机浏览器中,输入生成的公共 URL,加上您的天气查询接口的路径,例如 <code>http://a1b2c3d4.ngrok.io/api/w/zhuhai</code>,然后您应该能够看到返回的 JSON 天气数据。</p>
<h3 id="_20">检验办法<a class="headerlink" href="#_20" title="Permanent link">¶</a></h3>
<p>通过在手机浏览器中访问生成的公共 URL,加上您的天气查询接口的路径,来验证接口的功能和返回结果。确保您能够成功获取指定城市的天气数据。</p>
<h3 id="_21">其他方案<a class="headerlink" href="#_21" title="Permanent link">¶</a></h3>
<p>除了 ngrok,还有一些其他方案可以将本地接口发布到互联网中,例如使用反向代理工具、部署到云服务器等。但就简单性而言,ngrok 是一个非常方便且简单易用的工具,适合快速将本地接口发布到互联网上。</p>
<p>希望这些步骤和说明能够帮助您将本地接口发布到互联网中,并成功在手机浏览器中查询指定城市的天气情况。如果您有任何疑问,欢迎随时提问。</p>
<blockquote>
<blockquote>
<p>进入任何一个新环节时, 都值得请 AIGC 给出多种方案来对比理解, 拓展常识,决策方向...</p>
</blockquote>
</blockquote>
<ul>
<li>
<p>Q:但是, 通过 ngrok 发布本地 5000 端口的接口后,
访问说 您未获授权,无法查看此网页
这是为什么? 应该如何解决?谢谢</p>
</li>
<li>
<p>A: 这个问题通常是由于 ngrok 的免费版本限制导致的。ngrok 的免费版本在使用时会分配一个随机的子域名,但是这些子域名可能会被其他人使用过或者被滥用,因此有些网络会将其标记为不安全或受限制的网站,导致出现 "403 Forbidden" 的错误。</p>
</li>
</ul>
<p>为了解决这个问题,您可以考虑以下几种方法:</p>
<ol>
<li>
<p><strong>购买 ngrok 的付费版本</strong>:ngrok 提供了付费版本,付费版本可以获得稳定的域名和更多的功能。购买付费版本后,您将获得一个独特的域名,避免了被其他人滥用的风险。</p>
</li>
<li>
<p><strong>使用其他类似的工具</strong>:除了 ngrok,还有一些类似的工具可以将本地服务发布到互联网上,例如 localtunnel、serveo 等。您可以尝试使用其他工具来看是否能够解决这个问题。</p>
</li>
<li>
<p><strong>部署到云服务器</strong>:考虑将您的应用程序部署到云服务器上,例如使用 AWS、Azure、Google Cloud 等云服务商的免费套餐。这样可以获得一个稳定的公网 IP 地址,避免了被标记为不安全的问题。</p>
</li>
</ol>
<p>希望这些方法能够帮助您解决通过 ngrok 发布本地接口时出现的 "403 Forbidden" 错误。如果您有任何疑问,欢迎随时提问。</p>
<blockquote>
<blockquote>
<p>当前, 要快速检验对应方案是否可行, 并随时根据反馈组织新的问题...</p>
</blockquote>
</blockquote>
<ul>
<li>
<p>Q : 类似 ngrok 的工具, 比如 localtunnel、serveo 等 都有哪一些?
其中可以安装应用到 M1 芯片的 macOS 环境中的有哪一些?
推荐使用哪一种? 为什么?</p>
</li>
<li>
<p>A: 类似 ngrok 的工具有很多,其中一些比较常见的包括 localtunnel、serveo、Pagekite、ngrok2、yaler、frp 等。</p>
</li>
</ul>
<p>针对 M1 芯片的 macOS 环境,可以安装并使用以下工具:</p>
<ol>
<li>
<p><strong>localtunnel</strong>:localtunnel 是一个简单的工具,可以将本地的 HTTP 服务暴露到公共的互联网上。它是基于 Node.js 编写的,因此可以在 M1 芯片的 macOS 环境中运行。</p>
</li>
<li>
<p><strong>serveo</strong>:serveo 是另一个类似的工具,它提供了简单易用的方式将本地服务暴露到公网。serveo 也可以在 M1 芯片的 macOS 环境中运行。</p>
</li>
<li>
<p><strong>ngrok2</strong>:ngrok 的旧版本 ngrok2 也可以在 M1 芯片的 macOS 环境中运行,但需要确保安装了适用于 M1 芯片的版本。</p>
</li>
</ol>
<p>推荐使用 localtunnel 或 serveo,因为它们都是轻量级的工具,易于安装和使用。同时,它们在 M1 芯片的 macOS 环境中都能够正常运行,并且提供了稳定的服务。另外,这两个工具都有良好的社区支持和文档,方便用户进行学习和使用。</p>
<p>希望这些信息能够帮助您选择合适的工具。如果您有任何其他问题,欢迎随时提问。</p>
<ul>
<li>Q:看起来 serveo 更加简单, 那么, 如何用 serveo 将 flask 的 localhost:5000 接口反向代理到互联网中, 以便手机也可以访问?</li>
<li>A: 您可以按照以下步骤使用 Serveo 将 Flask 应用程序从本地代理到互联网上,以便手机也可以访问:</li>
</ul>
<h3 id="openssh">步骤一:安装 OpenSSH<a class="headerlink" href="#openssh" title="Permanent link">¶</a></h3>
<p>确保您的计算机上安装了 OpenSSH。大多数 macOS 和 Linux 系统都会默认安装 OpenSSH。如果您使用的是 Windows 系统,您可以通过 Windows Subsystem for Linux (WSL) 安装 OpenSSH。</p>
<h3 id="flask_5">步骤二:启动 Flask 应用程序<a class="headerlink" href="#flask_5" title="Permanent link">¶</a></h3>
<p>在终端中,导航到包含 Flask 应用程序的目录,并运行您的 Flask 应用程序:</p>
<div class="highlight"><pre><span></span><code>python<span class="w"> </span>app.py
</code></pre></div>
<h3 id="serveo">步骤三:使用 Serveo<a class="headerlink" href="#serveo" title="Permanent link">¶</a></h3>
<p>在终端中,运行以下命令将本地的 Flask 应用程序代理到互联网上:</p>
<div class="highlight"><pre><span></span><code>ssh<span class="w"> </span>-R<span class="w"> </span><span class="m">80</span>:localhost:5000<span class="w"> </span>serveo.net
</code></pre></div>
<p>这将创建一个公共 URL,将来自互联网的流量转发到您本地的 Flask 应用程序。</p>
<h3 id="_22">步骤四:验证接口<a class="headerlink" href="#_22" title="Permanent link">¶</a></h3>
<p>在终端中,您将看到生成的公共 URL,类似于 <code>http://your_url.serveo.net</code>。在手机浏览器中输入这个 URL,加上您的天气查询接口的路径,例如 <code>http://your_url.serveo.net/api/w/zhuhai</code>,然后您应该能够看到返回的 JSON 天气数据。</p>
<h3 id="_23">检验办法<a class="headerlink" href="#_23" title="Permanent link">¶</a></h3>
<p>通过在手机浏览器中访问生成的公共 URL,加上您的天气查询接口的路径,来验证接口的功能和返回结果。确保您能够成功获取指定城市的天气数据。</p>
<p>希望这些步骤能够帮助您使用 Serveo 将 Flask 应用程序代理到互联网上,以便手机也可以访问。如果您有任何疑问,欢迎随时提问。</p>
<ul>
<li>Q: 无法访问: 浏览器返回:
访问 3e3a3053f4d26c87df428f3b05fb393b.serveo.net 的请求遭到拒绝您未获授权,无法查看此网页。
HTTP ERROR 403</li>
</ul>
<p>在终端中, 可以看到:</p>
<p>HTTP request from 101.32.192.28 to https://3e3a3053f4d26c87df428f3b05fb393b.serveo.net/</p>
<p>有请求收到, 但是, 没有转发给 falsk 的服务, 这是为什么, 如何解决?
谢谢;</p>
<ul>
<li>A: 这个问题可能是由于 Serveo 无法正确将流量转发到您的本地 Flask 服务导致的。这可能是由于网络配置或防火墙问题引起的。</li>
</ul>
<p>为了解决这个问题,您可以尝试以下方法:</p>
<ol>
<li>
<p><strong>检查防火墙设置</strong>:确保您的本地计算机和网络防火墙允许来自 Serveo 的流量。有时防火墙会阻止外部流量进入本地计算机,导致无法访问您的服务。</p>
</li>
<li>
<p><strong>检查网络配置</strong>:如果您在公司或学校的网络环境中,可能存在网络配置限制,导致无法从外部访问本地服务。您可以尝试在家庭网络或其他网络环境中进行测试,看是否能够解决问题。</p>
</li>
<li>
<p><strong>尝试其他工具</strong>:如果问题仍然存在,您可以尝试使用其他类似的工具,例如 localtunnel 或 ngrok,看是否能够成功将本地服务代理到互联网上。</p>
</li>
<li>
<p><strong>联系 Serveo 支持</strong>:如果以上方法都无法解决问题,您可以联系 Serveo 的支持团队,寻求他们的帮助和支持。</p>
</li>
</ol>
<p>希望这些方法能够帮助您解决问题,成功将您的本地 Flask 服务代理到互联网上。如果您有任何其他问题,欢迎随时提问。</p>
<blockquote>
<blockquote>
<p>至此, 其实一个随时查询指定城市天气的 MVP 工具已经开发完成, 只是要允许外网可以访问, 这已经不是开发问题, 而是发布和运维问题了...在直播视频中进行了另外的尝试, 已经超出 AIGC 辅助开发的话题, 就此打住</p>
</blockquote>
</blockquote>
<p><img alt="serveo" src="https://ipic.zoomquiet.top/2024-01-24-zshot%202024-01-23%2020.44.10.jpg"/></p>
<p>直播视频中, 是跳到了 HK 的主机中, 重新运行工程,
就可以访问对应服务了...</p>
<h2 id="summary">summary<a class="headerlink" href="#summary" title="Permanent link">¶</a></h2>
<blockquote>
<p>最小最实用 🎃程序员AIGC工具包</p>
</blockquote>
<ul>
<li>一个稳定流畅的网络</li>
<li>一个友好精确的类 ChatGPT 引擎, 推荐 devv.ai</li>
<li>一个友好灵活的编辑环境, 推荐 VSCode</li>
<li>一个清晰具体的目标, 是的目标不明确时, 是无法提出有效问题的, 没有可靠的问题/提示词, 当然也就不可能生成可靠的回答</li>
<li>一组层次良好,前后递进的问题, 值得包含的关键词:<ul>
<li>有哪些方案?</li>
<li>给出具体示例代码</li>
<li>解释关键行为</li>
<li>说明检验办法</li>
<li>...以及, 谢谢, 并肯定对应回答, <ul>
<li>就算是为了人类未来, 也请保持基本礼貌</li>
<li>其实, 这是 AIGC 引擎的魔法词, 用来加强有关参数的...</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>当然, 在以上 <code>工具包</code> 中, 还隐藏了一个更加关键以及底层的能力:</p>
<p>语文素质, 如果你本身在自然对话中, 都无法流畅的阐述自己的想法,
那么, 面对无限耐心的知识的 AIGC , 基本上也难以获得值得参考的回答;</p>
<p>进一步的, 在中文语文能力之上, 有英文沟通能力更加好, 一个检验方法是:</p>
<ul>
<li>如果你手工输入的英文, 用 google 翻译过来的中文</li>
<li>和你手工输入的中文, 基本一致,</li>
<li>说明, 你具有了 AI 时代思维模式, 可以用中文阐述和英文一致的思想;</li>
</ul>
<h2 id="refer">refer.<a class="headerlink" href="#refer" title="Permanent link">¶</a></h2>
<ul>
<li>过程视频: <a href="https://studio.youtube.com/video/VbCJhD3TDtA/edit">AIGCxZhuhai[demo show]通用编程AI辅助过程 - YouTube</a></li>
<li>代码仓库: <a href="https://github.com/AIGCx/zhuhai">AIGCx/zhuhai: demo show anything about AIGC</a></li>
</ul>
<p>SEE:</p>
<ul>
<li><a href="https://www.bmpi.dev/dev/chatgpt-development-notes/pair-programming/">我与ChatGPT结对编程的体验 · BMPI</a></li>
<li><a href="https://baoyu.io/translations/ai/how-i-use-chatgpt-daily-scientist-coder-perspective">我每天是如何使用 ChatGPT 的(从科学家和开发者的视角) [译] | 宝玉的分享</a></li>
<li><a href="https://missing-semester-cn.github.io/">计算机教育中缺失的一课 · the missing semester of your cs education</a></li>
<li><a href="https://braydie.gitbooks.io/how-to-be-a-programmer/content/zh/">Introduction · How to be a Programmer</a></li>
<li>...</li>
</ul>带生成器的惰性递归2023-03-22T00:00:00+08:002023-03-22T17:59:39+08:00Zoom.Quiettag:blog.zoomquiet.io,2023-03-22:/lazy_recursion_with_generators.html
<h2 id="background">background<a class="headerlink" href="#background" title="Permanent link">¶</a></h2>
<p>原文: <a href="https://tushar.lol/post/recursive-generators/">Lazy recursion, with generators</a></p>
<p>来自 <a href="https://weekly.pychina.org/issue/issue-569.html">蠎周刊 PyCoder 569 ~蠎周刊 ~汇集全球蠎事儿 ;-)</a> 的推荐</p>
<h2 id="_1">快译<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p>此文, 准备研究 Python 的生成器,
并用之来也又和并递归 …</p>
<h2 id="background">background<a class="headerlink" href="#background" title="Permanent link">¶</a></h2>
<p>原文: <a href="https://tushar.lol/post/recursive-generators/">Lazy recursion, with generators</a></p>
<p>来自 <a href="https://weekly.pychina.org/issue/issue-569.html">蠎周刊 PyCoder 569 ~蠎周刊 ~汇集全球蠎事儿 ;-)</a> 的推荐</p>
<h2 id="_1">快译<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p>此文, 准备研究 Python 的生成器,
并用之来也又和并递归代码的内存使用;</p>
<h3 id="_2">当代码调用自己时<a class="headerlink" href="#_2" title="Permanent link">¶</a></h3>
<blockquote>
<p>When the code calls itself</p>
</blockquote>
<p>你知道什么是递归;
就是函数调用自己,
如果要复习一下, 先看个示例:</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">factorial</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="c1"># base case</span>
<span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">1</span>
<span class="c1"># recurse</span>
<span class="k">return</span> <span class="n">n</span> <span class="o">*</span> <span class="n">factorial</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
</code></pre></div>
<p>要理解调用自身是如何工作的,
这是 factorial(5) 过程分解:</p>
<div class="highlight"><pre><span></span><code><span class="n">factorial</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="o">=</span> <span class="mi">5</span> <span class="o">*</span> <span class="n">factorial</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
<span class="o">=</span> <span class="mi">5</span> <span class="o">*</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">factorial</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="o">=</span> <span class="mi">5</span> <span class="o">*</span> <span class="mi">4</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">*</span> <span class="n">factorial</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="o">=</span> <span class="mi">5</span> <span class="o">*</span> <span class="mi">4</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">factorial</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="o">=</span> <span class="mi">5</span> <span class="o">*</span> <span class="mi">4</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">*</span> <span class="mi">1</span>
<span class="o">=</span> <span class="mi">120</span>
</code></pre></div>
<p>1 的值来自 factorial(1),
然后返回调用栈时继续乘以 2,3 等等;</p>
<h3 id="_3">何必呢?<a class="headerlink" href="#_3" title="Permanent link">¶</a></h3>
<blockquote>
<p>Why bother?</p>
</blockquote>
<p>以上递归当然可以宑成 for 循环:</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">factorial</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="n">product</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="n">product</span> <span class="o">=</span> <span class="n">product</span> <span class="o">*</span> <span class="n">i</span>
<span class="k">return</span> <span class="n">product</span>
</code></pre></div>
<p>那为什么要费心写成递归呢?</p>
<p>事实上, 某些逻辑本质上就是递归的;
一个很好的实例就是打印出文件夹中所有路径,
就象 find 指令作的那样;
这是我一个项目中相关代码:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>find<span class="w"> </span>./src
./src
./src/pylox
./src/pylox/tokens.py
./src/pylox/utils
./src/pylox/utils/__init__.py
./src/pylox/utils/visitor.py
./src/pylox/utils/ast_printer.py
./src/pylox/__init__.py
./src/pylox/lexer.py
./src/pylox/__main__.py
./src/pylox/expr.py
./src/pylox/py.typed
./src/pylox/parser.py
</code></pre></div>
<p>find 工作原理相当简单;
以下是把不即出文件夹所有内容的流程:</p>
<ul>
<li>打印文件夹路径</li>
<li>获得文件夹中所有东西</li>
<li>对于文件夹中每个项目:<ul>
<li>如果是个文件, 就打印出文件的路径</li>
<li>我哪来就是文件夹, 打印出这个子文件夹中的所有内容</li>
</ul>
</li>
</ul>
<p>请注意, 最后一条指令(打印子文件夹中的所有内容)
只是原始任务的一小部分;
递归就非常适合此类任务;</p>
<h3 id="_4">编程时间<a class="headerlink" href="#_4" title="Permanent link">¶</a></h3>
<blockquote>
<p>Time to code</p>
</blockquote>
<p>让我们将这些指令转化为代码;
将使用一个假设的文件结构进行检验;</p>
<p>模拟以下树形结构:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>tree<span class="w"> </span>/
/
├──<span class="w"> </span>etc
│<span class="w"> </span>├──<span class="w"> </span>passwd
│<span class="w"> </span>└──<span class="w"> </span>shadow
└──<span class="w"> </span>usr
<span class="w"> </span>├──<span class="w"> </span>bin
<span class="w"> </span>│<span class="w"> </span>├──<span class="w"> </span>cat
<span class="w"> </span>│<span class="w"> </span>└──<span class="w"> </span>ls
<span class="w"> </span>└──<span class="w"> </span>lib
<span class="w"> </span>├──<span class="w"> </span>my_lib
<span class="w"> </span>└──<span class="w"> </span>gcc
<span class="w"> </span>└──<span class="w"> </span>x86_64-linux-gnu
</code></pre></div>
<p>Python 代码的话:</p>
<div class="highlight"><pre><span></span><code><span class="n">file_tree</span> <span class="o">=</span> <span class="p">[</span><span class="s1">''</span><span class="p">,</span> <span class="p">[</span>
<span class="p">[</span><span class="s1">'etc'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'passwd'</span><span class="p">,</span> <span class="s1">'shadow'</span><span class="p">]],</span>
<span class="p">[</span><span class="s1">'usr'</span><span class="p">,</span> <span class="p">[</span>
<span class="p">[</span><span class="s1">'bin'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'cat'</span><span class="p">,</span> <span class="s1">'ls'</span><span class="p">]],</span>
<span class="p">[</span><span class="s1">'lib'</span><span class="p">,</span> <span class="p">[</span>
<span class="s1">'my_lib'</span><span class="p">,</span>
<span class="p">[</span><span class="s1">'gcc'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'x86_64-linux-gnu'</span><span class="p">]]</span>
<span class="p">]]</span>
<span class="p">]]</span>
<span class="p">]]</span>
<span class="k">def</span> <span class="nf">print_paths_recursive</span><span class="p">(</span><span class="n">folder</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="p">()):</span>
<span class="n">name</span><span class="p">,</span> <span class="n">contents</span> <span class="o">=</span> <span class="n">folder</span>
<span class="n">path</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">path</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'/'</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">path</span><span class="p">))</span>
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">contents</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
<span class="c1"># This is a file, print out its path</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'/'</span><span class="o">.</span><span class="n">join</span><span class="p">((</span><span class="o">*</span><span class="n">path</span><span class="p">,</span> <span class="n">item</span><span class="p">)))</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># This is a folder, recurse</span>
<span class="n">print_paths_recursive</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">path</span><span class="p">)</span>
<span class="n">print_paths_recursive</span><span class="p">(</span><span class="n">file_tree</span><span class="p">)</span>
</code></pre></div>
<p>以及输出:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>python<span class="w"> </span>find.py
/etc
/etc/passwd
/etc/shadow
/usr
/usr/bin
/usr/bin/cat
/usr/bin/ls
/usr/lib
/usr/lib/my_lib
/usr/lib/gcc
/usr/lib/gcc/x86_64-linux-gnu
Fairly<span class="w"> </span>straightforward.
</code></pre></div>
<p>转折点来了:
你会如何让这个函数返回所有路径呢?</p>
<h3 id="_5">递归和集合<a class="headerlink" href="#_5" title="Permanent link">¶</a></h3>
<blockquote>
<p>Recursion and collection</p>
</blockquote>
<p>浰不编写递归代码来收集一些数据是很常见的;
必须收集所有文件大又得那而不是将其打印出来就是一个明显的实例;</p>
<p>为此,我们嘦进行相当小的更改:</p>
<p>该函数现在将返回路径列表;
这是递归的一个重要区别,
因为,函数之前没有返回任何东西;
我们将追加到路径列表, 而不是打印出内容;
这就将接收子路径作为返回值,
而不是仅仅进行递归调用,
并将所有返回追加到最终答案数据集中;</p>
<p>这是修改后的代码:</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">get_paths_recursive</span><span class="p">(</span><span class="n">folder</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="p">()):</span>
<span class="n">paths</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">name</span><span class="p">,</span> <span class="n">contents</span> <span class="o">=</span> <span class="n">folder</span>
<span class="n">path</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">path</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
<span class="n">paths</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">'/'</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">path</span><span class="p">))</span>
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">contents</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
<span class="c1"># This is a file, append its path</span>
<span class="n">paths</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">'/'</span><span class="o">.</span><span class="n">join</span><span class="p">((</span><span class="o">*</span><span class="n">path</span><span class="p">,</span> <span class="n">item</span><span class="p">)))</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># This is a folder, recurse and append all subpaths</span>
<span class="k">for</span> <span class="n">subpath</span> <span class="ow">in</span> <span class="n">get_paths_recursive</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">path</span><span class="p">):</span>
<span class="n">paths</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">subpath</span><span class="p">)</span>
<span class="k">return</span> <span class="n">paths</span>
<span class="n">paths</span> <span class="o">=</span> <span class="n">get_paths_recursive</span><span class="p">(</span><span class="n">file_tree</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">paths</span><span class="p">)</span>
</code></pre></div>
<p>输出:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>python<span class="w"> </span>find.py
<span class="o">[</span><span class="s1">''</span>,<span class="w"> </span><span class="s1">'/etc'</span>,<span class="w"> </span><span class="s1">'/etc/passwd'</span>,<span class="w"> </span><span class="s1">'/etc/shadow'</span>,<span class="w"> </span><span class="s1">'/usr'</span>,<span class="w"> </span><span class="s1">'/usr/bin'</span>,
<span class="s1">'/usr/bin/cat'</span>,<span class="w"> </span><span class="s1">'/usr/bin/ls'</span>,<span class="w"> </span><span class="s1">'/usr/lib'</span>,<span class="w"> </span><span class="s1">'/usr/lib/my_lib'</span>,
<span class="s1">'/usr/lib/gcc'</span>,<span class="w"> </span><span class="s1">'/usr/lib/gcc/x86_64-linux-gnu'</span><span class="o">]</span>
</code></pre></div>
<h3 id="_6">问题来了<a class="headerlink" href="#_6" title="Permanent link">¶</a></h3>
<blockquote>
<p>The problem</p>
</blockquote>
<p>如果收集很多文件夹, 问题就出现了;
如果你的目录中有数千或是数百万个文件和文件夹,
将所有文件和文件夹存储在一个列表中,
可能就很麻烦, 原因有两个:</p>
<ul>
<li>你的内存使用会随机飊升;列表可以增长到多大是没有限制的,因此,从技术上讲, 你甚至可能耗尽内存;</li>
<li>如果你只关心文件中的几个项目,那你就不走运了 --- 算法会找出每个子文件夹,然后,你才能对结果数据作些其它事儿;</li>
</ul>
<p>本质上,这是种急性评估的算法;
避免存储所有数据的唯一方法就是直接在函数内部执行任务,
就像我们在直接打印时作的那样;
但是, 这又强烈的将我们的代码和业务进行了耦合;</p>
<h3 id="_7">解决方案<a class="headerlink" href="#_7" title="Permanent link">¶</a></h3>
<blockquote>
<p>The solution</p>
</blockquote>
<p>所以,总结一下我们的问题:
我们想要对任意文件路径运行任意需要的执行任何代码;</p>
<p>任务可能是将其打印出来,又或是将其存储到列表中或是其它:</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">get_paths_recursive</span><span class="p">(</span><span class="n">folder</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="p">()):</span>
<span class="n">name</span><span class="p">,</span> <span class="n">contents</span> <span class="o">=</span> <span class="n">folder</span>
<span class="n">path</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">path</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
<span class="c1">## Do something with the `path` here,</span>
<span class="c1">## Example: print(path), or paths.append(path)</span>
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">contents</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
<span class="c1">## Do something with the `path + item` here...</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">for</span> <span class="n">subpath</span> <span class="ow">in</span> <span class="n">get_paths_recursive</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">path</span><span class="p">):</span>
<span class="c1">## Do something with the `subpath` here...</span>
<span class="k">return</span> <span class="n">paths</span>
</code></pre></div>
<p>Python 已经为我们提供了一个非常强大的结构来解决这一问题,
就是生成器;</p>
<p>可以可能在其它一些上下文中听说过生成器,
例如:</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">gen</span><span class="p">():</span>
<span class="k">yield</span> <span class="mi">10</span>
<span class="k">yield</span> <span class="mi">20</span>
<span class="k">yield</span> <span class="mi">10</span>
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">gen</span><span class="p">():</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Got:'</span><span class="p">,</span> <span class="n">item</span><span class="p">)</span>
<span class="c1"># Got: 10</span>
<span class="c1"># Got: 20</span>
<span class="c1"># Got: 10</span>
</code></pre></div>
<p>但是, 关于生成器有一个鲜为人知的事实:
人家可以在代码中两点间移动你的 evaluation;</p>
<p>我的意思是这样的:</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">gen</span><span class="p">():</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Start!"</span><span class="p">)</span>
<span class="k">yield</span> <span class="mi">1</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Now we're calculating stuff in gen()"</span><span class="p">)</span>
<span class="n">value</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">))</span>
<span class="k">yield</span> <span class="n">value</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Last value!"</span><span class="p">)</span>
<span class="k">yield</span> <span class="mi">42</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Done."</span><span class="p">)</span>
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">gen</span><span class="p">():</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Doing things with </span><span class="si">{</span><span class="n">item</span><span class="si">}</span><span class="s2">..."</span><span class="p">)</span>
</code></pre></div>
<p>你可以看到执行是如何在 gen() 和 for 循环间来回进行的:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>py<span class="w"> </span>a.py
Start!
Doing<span class="w"> </span>things<span class="w"> </span>with<span class="w"> </span><span class="m">1</span>...
Now<span class="w"> </span>we<span class="err">'</span>re<span class="w"> </span>calculating<span class="w"> </span>stuff<span class="w"> </span><span class="k">in</span><span class="w"> </span>gen<span class="o">()</span>
Doing<span class="w"> </span>things<span class="w"> </span>with<span class="w"> </span><span class="m">45</span>...
Last<span class="w"> </span>value!
Doing<span class="w"> </span>things<span class="w"> </span>with<span class="w"> </span><span class="m">42</span>...
Done.
</code></pre></div>
<p>这正是我们在本例中需要的:
每当我们有新路径时, 我们都需要执行上下文返回给主代码;
所以, 我们可以将生成器的控制权交给循环:</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">get_paths_generator</span><span class="p">(</span><span class="n">folder</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="p">()):</span>
<span class="n">name</span><span class="p">,</span> <span class="n">contents</span> <span class="o">=</span> <span class="n">folder</span>
<span class="n">path</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">path</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
<span class="k">yield</span> <span class="s1">'/'</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">contents</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
<span class="k">yield</span> <span class="s1">'/'</span><span class="o">.</span><span class="n">join</span><span class="p">((</span><span class="o">*</span><span class="n">path</span><span class="p">,</span> <span class="n">item</span><span class="p">))</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">for</span> <span class="n">subpath</span> <span class="ow">in</span> <span class="n">get_paths_generator</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">path</span><span class="p">):</span>
<span class="k">yield</span> <span class="n">subpath</span>
</code></pre></div>
<p>现在, 最好的部分来了,
我们可以创建原始用例, 打印和储存列表都很容易:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>python<span class="w"> </span>-i<span class="w"> </span>find.py
>>><span class="w"> </span><span class="k">for</span><span class="w"> </span>path<span class="w"> </span><span class="k">in</span><span class="w"> </span>get_paths_generator<span class="o">(</span>file_tree<span class="o">)</span>:
...<span class="w"> </span>print<span class="o">(</span>path<span class="o">)</span>
/etc
/etc/passwd
/etc/shadow
/usr
/usr/bin
/usr/bin/cat
/usr/bin/ls
/usr/lib
/usr/lib/my_lib
/usr/lib/gcc
/usr/lib/gcc/x86_64-linux-gnu
>>><span class="w"> </span>list<span class="o">(</span>get_paths_generator<span class="o">(</span>file_tree<span class="o">))</span>
<span class="o">[</span><span class="s1">''</span>,<span class="w"> </span><span class="s1">'/etc'</span>,<span class="w"> </span><span class="s1">'/etc/passwd'</span>,<span class="w"> </span><span class="s1">'/etc/shadow'</span>,<span class="w"> </span><span class="s1">'/usr'</span>,<span class="w"> </span><span class="s1">'/usr/bin'</span>,
<span class="s1">'/usr/bin/cat'</span>,<span class="w"> </span><span class="s1">'/usr/bin/ls'</span>,<span class="w"> </span><span class="s1">'/usr/lib'</span>,<span class="w"> </span><span class="s1">'/usr/lib/my_lib'</span>,
<span class="s1">'/usr/lib/gcc'</span>,<span class="w"> </span><span class="s1">'/usr/lib/gcc/x86_64-linux-gnu'</span><span class="o">]</span>
</code></pre></div>
<p>这种解决方案要灵活的多,
并且, 永远不会像原先方案那样出现急切求值问题;</p>
<h3 id="yield-from">奖励: yield from<a class="headerlink" href="#yield-from" title="Permanent link">¶</a></h3>
<blockquote>
<p>Bonus: yield from</p>
</blockquote>
<p>原先使用 append 来存储路径的代码可以进行一儿改进:
你可以使用 list.extend, 而不是编写一个 for 循环来逐一追加每个子路径:</p>
<div class="highlight"><pre><span></span><code> <span class="c1"># ...</span>
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">contents</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
<span class="n">paths</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">'/'</span><span class="o">.</span><span class="n">join</span><span class="p">((</span><span class="o">*</span><span class="n">path</span><span class="p">,</span> <span class="n">item</span><span class="p">)))</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1">## REPLACING THIS LOOP:</span>
<span class="c1"># for subpath in get_paths_recursive(item, path):</span>
<span class="c1"># paths.append(subpath)</span>
<span class="n">paths</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">get_paths_recursive</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">path</span><span class="p">))</span>
</code></pre></div>
<p>两样的事儿, 可以在我们的生成器解决方案中完成,
使用 yield from gen():</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">get_paths_generator</span><span class="p">(</span><span class="n">folder</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="p">()):</span>
<span class="n">name</span><span class="p">,</span> <span class="n">contents</span> <span class="o">=</span> <span class="n">folder</span>
<span class="n">path</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">path</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
<span class="k">yield</span> <span class="s1">'/'</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">contents</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
<span class="k">yield</span> <span class="s1">'/'</span><span class="o">.</span><span class="n">join</span><span class="p">((</span><span class="o">*</span><span class="n">path</span><span class="p">,</span> <span class="n">item</span><span class="p">))</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">yield from</span> <span class="n">get_paths_generator</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">path</span><span class="p">)</span>
</code></pre></div>
<p>yield from 将产另外一个生成器中所有的值, 一个接一个;</p>
<h3 id="_8">脚注<a class="headerlink" href="#_8" title="Permanent link">¶</a></h3>
<blockquote>
<p>Footer</p>
</blockquote>
<p>以上, 希望你发现使用生成器来改进 Python 中新(和旧)递归代码;
另外, James Powell 有过一个很给力的演讲:
<a href="https://www.youtube.com/watch?v=XEn_99daJro">Python Generators || James Powell - YouTube</a></p>
<p>有关生成器如何拓展出更多的想法,
如果你有兴趣的话, 值得看看;</p>
<h2 id="refer">refer.<a class="headerlink" href="#refer" title="Permanent link">¶</a></h2>
<p>每一位认真的技术 blogger 都有很多值得精读的积累,比如这位<a href="https://snippets.live/">Tushar Sadhwani</a>的:</p>
<h2 id="-understanding-all-of-python-through-its-builtins">- <a href="https://tushar.lol/post/builtins/" title="Understanding all of Python, through its builtins">Understanding all of Python, through its builtins</a><a class="headerlink" href="#-understanding-all-of-python-through-its-builtins" title="Permanent link">¶</a></h2>Python 中的字典调度模式2023-02-09T18:42:00+08:002023-02-09T18:00:27+08:00ZoomQuiettag:blog.zoomquiet.io,2023-02-09:/230209-dict-dispatch-pattern-in-python.html<p>Pythonic/ 字典的神奇功能</p>
<p>原文: <a href="https://martinheinz.dev/blog/90">Dictionary Dispatch Pattern in Python | Martin Heinz | Personal Website & Blog</a></p>
<p>是否曾经写过一堆 if/else 或是一个巨大的 match/case ,
其中所有语句只是为了匹配一值, 想知道如何将这种事儿简洁又可读嘛?</p>
<p>如果这种场景,那么 字典调度模式 可能就是适合的工具;
通过字典分派,可以通过简单的查找 Python 的字典来替代任何条件组,
而且有很多姿势可以搞...</p>
<p>If so, then dictionary dispatch pattern might be a tool for you. With dictionary dispatch we can replace any block of conditionals with a simple lookup into Python's dict- here's how it works...</p>
<h2 id="lambda">使用 Lambda 函数<a class="headerlink" href="#lambda" title="Permanent link">¶</a></h2>
<p>字典分派的整个思想是我们可以根据变量的值运行不同的函数,
而不是对每个值使用条件语句来指向不同函数;</p>
<p>如果没有字典调度, 我们将不得不使用 if/else 或是 match/case 判别块:</p>
<div class="highlight"><pre><span></span><code><span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">3</span>
<span class="n">operation</span> <span class="o">=</span> <span class="s2">"add"</span>
<span class="k">if</span> <span class="n">operation</span> <span class="o">==</span> <span class="s2">"add"</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="n">y</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">operation</span> <span class="o">==</span> <span class="s2">"mul"</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="n">x</span> <span class="o">*</span> <span class="n">y</span><span class="p">)</span>
<span class="c1"># ---------------</span>
<span class="k">match</span> <span class="n">operation</span><span class="p">:</span>
<span class="k">case</span> <span class="s2">"add"</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="n">y</span><span class="p">)</span>
<span class="k">case</span> <span class="s2">"mul"</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="n">x</span> <span class="o">*</span> <span class="n">y</span><span class="p">)</span>
</code></pre></div>
<p>虽然这样在 if 或是 case 数量少感觉还成,
但是,随着选项数量的增加, 可能就变得冗长难以阅读和维护了;</p>
<p>作为替代,我们可以进行以下转化:</p>
<div class="highlight"><pre><span></span><code><span class="n">functions</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">"add"</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span><span class="p">,</span>
<span class="s2">"mul"</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="n">x</span> <span class="o">*</span> <span class="n">y</span>
<span class="p">}</span>
<span class="nb">print</span><span class="p">(</span><span class="n">functions</span><span class="p">[</span><span class="s2">"add"</span><span class="p">](</span><span class="mi">5</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>
<span class="c1"># 8</span>
<span class="nb">print</span><span class="p">(</span><span class="n">functions</span><span class="p">[</span><span class="s2">"mul"</span><span class="p">](</span><span class="mi">5</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>
<span class="c1"># 15</span>
</code></pre></div>
<p>实现字典分派最简单方式就是使用 lambda 函数;
在原来的, 我们将每个 lambda 函数分配给字典的一个键;
然后, 就可以通过查找键名并选择性的传入参数来调用到该函数(行内匿名声明的);</p>
<p>当你的操作可以用单行代码表示时,
使用 lambda 是合适的, 但是, 通常使用适当的 Python 函数才是可行的...</p>
<p>(<code>是也乎</code>:</p>
<p>不过,也不一定,参考: <a href="https://pycoders.com/link/10308/web">flatliner-src: 将 Python 程序转换为一行代码</a></p>
<p>真的有项目可以自动将任何函数一键转化为由 lambda 串接的一行代码.</p>
<p>)</p>
<h2 id="_1">使用适当的功能<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p>lambda 函数非常适合简单的情况,
但是, 你可能希望分派需要多行代码的函数:</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
<span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
<span class="k">def</span> <span class="nf">mul</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
<span class="k">return</span> <span class="n">x</span> <span class="o">*</span> <span class="n">y</span>
<span class="n">functions</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">"add"</span><span class="p">:</span> <span class="n">add</span><span class="p">,</span>
<span class="s2">"mul"</span><span class="p">:</span> <span class="n">mul</span><span class="p">,</span>
<span class="p">}</span>
<span class="nb">print</span><span class="p">(</span><span class="n">functions</span><span class="p">[</span><span class="s2">"add"</span><span class="p">](</span><span class="mi">5</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>
<span class="c1"># 8</span>
<span class="nb">print</span><span class="p">(</span><span class="n">functions</span><span class="p">[</span><span class="s2">"mul"</span><span class="p">](</span><span class="mi">5</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>
<span class="c1"># 15</span>
</code></pre></div>
<p>使用适当函数时, 唯一的区别是必须在字典之外定义,
毕竟 Python 暂时不允许内联函数定义;
虽然, 这看起来有点儿烦, 可读性也差,
但是, 在我看来, 这也迫使你编写更加清晰/可测试的代码;</p>
<h2 id="_2">默认结果<a class="headerlink" href="#_2" title="Permanent link">¶</a></h2>
<p>如果你使用此东西方来模拟 match/case 语句,
那么应该考虑在字典键不存在时使用默认值:</p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">defaultdict</span>
<span class="n">cases</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="k">lambda</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="k">lambda</span> <span class="o">*</span><span class="n">a</span><span class="p">:</span> <span class="s2">"Invalid option"</span><span class="p">,</span> <span class="p">{</span>
<span class="s2">"add"</span><span class="p">:</span> <span class="n">add</span><span class="p">,</span>
<span class="s2">"mul"</span><span class="p">:</span> <span class="n">mul</span><span class="p">,</span>
<span class="p">})</span>
<span class="nb">print</span><span class="p">(</span><span class="n">cases</span><span class="p">[</span><span class="s2">"add"</span><span class="p">](</span><span class="mi">5</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>
<span class="c1"># 8</span>
<span class="nb">print</span><span class="p">(</span><span class="n">cases</span><span class="p">[</span><span class="s2">"_"</span><span class="p">](</span><span class="mi">5</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>
<span class="c1"># Invalid option</span>
</code></pre></div>
<p>这段代码利用了 defaultdict,
第一个参数指定了 "默认工厂",
这是一个在找不到匹配键时调用的函数;
你也可能注意到在此,使用了两个 lambda 函数 --- 第一个是用来捕获传递过来的任意数量参数,
第二个是因为我们需要返回一个可以调用的函数;</p>
<p>This snippet leverages defaultdict, who's first argument specifies the "default factory", which is a function that will be called when key is not found. You will notice that we used 2 lambda functions here - first is there to catch any number of arguments passed to it, and the second is there because we need to return a callable.</p>
<h2 id="_3">传参<a class="headerlink" href="#_3" title="Permanent link">¶</a></h2>
<p>我们已经在前述所有示例中看到,
将参数传递给字典中的函数非常简单,
得是不是,如果你想在将参数传递给函数之前对其进行操作应该如何呢?</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">handle_event</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Handling event in 'handler_event' with </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
<span class="k">return</span> <span class="n">e</span>
<span class="k">def</span> <span class="nf">handle_other_event</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Handling event in 'handle_other_event' with </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
<span class="k">return</span> <span class="n">e</span>
<span class="c1"># With lambda:</span>
<span class="n">functions</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">"event1"</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">arg</span><span class="p">:</span> <span class="n">handle_event</span><span class="p">(</span><span class="n">arg</span><span class="p">[</span><span class="s2">"some-key"</span><span class="p">]),</span>
<span class="s2">"event2"</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">arg</span><span class="p">:</span> <span class="n">handle_other_event</span><span class="p">(</span><span class="n">arg</span><span class="p">[</span><span class="s2">"some-other-key"</span><span class="p">]),</span>
<span class="p">}</span>
<span class="n">event</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">"some-key"</span><span class="p">:</span> <span class="s2">"value"</span><span class="p">,</span>
<span class="s2">"some-other-key"</span><span class="p">:</span> <span class="s2">"different value"</span><span class="p">,</span>
<span class="p">}</span>
<span class="nb">print</span><span class="p">(</span><span class="n">functions</span><span class="p">[</span><span class="s2">"event1"</span><span class="p">](</span><span class="n">event</span><span class="p">))</span>
<span class="c1"># Handling event in 'handler_event' with value</span>
<span class="c1"># value</span>
<span class="nb">print</span><span class="p">(</span><span class="n">functions</span><span class="p">[</span><span class="s2">"event2"</span><span class="p">](</span><span class="n">event</span><span class="p">))</span>
<span class="c1"># Handling event in 'handle_other_event' with different value</span>
<span class="c1"># different value</span>
</code></pre></div>
<p>第一个选项是用 lambda 函数,
允许我们 -- 例如 -- 在参数载荷(payload)中查找特定键, 如上所示;</p>
<p>另一种选择是使用 parital 来"冻结"参数,
但是, 这要求你在定义字典之前拥有参数/载荷(payload):</p>
<div class="highlight"><pre><span></span><code><span class="n">event</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">"some-key"</span><span class="p">:</span> <span class="s2">"value"</span><span class="p">,</span>
<span class="s2">"some-other-key"</span><span class="p">:</span> <span class="s2">"different value"</span><span class="p">,</span>
<span class="p">}</span>
<span class="n">functions</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">"event1"</span><span class="p">:</span> <span class="n">partial</span><span class="p">(</span><span class="n">handle_event</span><span class="p">,</span> <span class="n">event</span><span class="p">[</span><span class="s2">"some-key"</span><span class="p">]),</span>
<span class="s2">"event2"</span><span class="p">:</span> <span class="n">partial</span><span class="p">(</span><span class="n">handle_other_event</span><span class="p">,</span> <span class="n">event</span><span class="p">[</span><span class="s2">"some-other-key"</span><span class="p">]),</span>
<span class="p">}</span>
<span class="nb">print</span><span class="p">(</span><span class="n">functions</span><span class="p">[</span><span class="s2">"event1"</span><span class="p">]())</span>
<span class="c1"># Handling event in 'handler_event' with value</span>
<span class="c1"># value</span>
<span class="nb">print</span><span class="p">(</span><span class="n">functions</span><span class="p">[</span><span class="s2">"event2"</span><span class="p">]())</span>
<span class="c1"># Handling event in 'handle_other_event' with different value</span>
<span class="c1"># different value</span>
</code></pre></div>
<h2 id="_4">真实世界<a class="headerlink" href="#_4" title="Permanent link">¶</a></h2>
<p>到目前为止,我们只实验了类似 hallo-world 级别的示例;
字典分派在现实世界中有很多用例,
所以, 让我们游览一些:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># parse_args.py</span>
<span class="kn">import</span> <span class="nn">argparse</span>
<span class="n">functions</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">"add"</span><span class="p">:</span> <span class="n">add</span><span class="p">,</span>
<span class="s2">"mul"</span><span class="p">:</span> <span class="n">mul</span><span class="p">,</span>
<span class="p">}</span>
<span class="n">parser</span> <span class="o">=</span> <span class="n">argparse</span><span class="o">.</span><span class="n">ArgumentParser</span><span class="p">()</span>
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
<span class="s2">"operation"</span><span class="p">,</span>
<span class="n">choices</span><span class="o">=</span><span class="p">[</span><span class="s2">"add"</span><span class="p">,</span> <span class="s2">"mul"</span><span class="p">],</span>
<span class="n">help</span><span class="o">=</span><span class="s2">"operation to perform (add, mul)"</span><span class="p">,</span>
<span class="p">)</span>
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
<span class="s2">"x"</span><span class="p">,</span>
<span class="nb">type</span><span class="o">=</span><span class="nb">int</span><span class="p">,</span>
<span class="n">help</span><span class="o">=</span><span class="s2">"first number"</span><span class="p">,</span>
<span class="p">)</span>
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
<span class="s2">"y"</span><span class="p">,</span>
<span class="nb">type</span><span class="o">=</span><span class="nb">int</span><span class="p">,</span>
<span class="n">help</span><span class="o">=</span><span class="s2">"second number"</span><span class="p">,</span>
<span class="p">)</span>
<span class="n">args</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span>
<span class="n">answer</span> <span class="o">=</span> <span class="n">functions</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">operation</span><span class="p">,)(</span><span class="n">args</span><span class="o">.</span><span class="n">x</span><span class="p">,</span> <span class="n">args</span><span class="o">.</span><span class="n">y</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">answer</span><span class="p">)</span>
</code></pre></div>
<p>首先是解析 CLI 参数;
这里我们使用内置的 argparse 模块来创建一个简单的 CLI 应用程序;
此处的得碊主要包含定义字典和为 CLI 设置 3 个可能的参数;</p>
<p>从 CLI 调用时,我们将获得以下内容:</p>
<div class="highlight"><pre><span></span><code><span class="n">python</span> <span class="n">parse_args</span><span class="o">.</span><span class="n">py</span>
<span class="c1"># usage: parse_args.py [-h] {add,mul} x y</span>
<span class="c1"># parse_args.py: error: the following arguments are required: operation, x, y</span>
<span class="n">python</span> <span class="n">parse_args</span><span class="o">.</span><span class="n">py</span> <span class="n">add</span> <span class="mi">1</span> <span class="mi">2</span>
<span class="c1"># 8</span>
<span class="n">python</span> <span class="n">parse_args</span><span class="o">.</span><span class="n">py</span> <span class="n">mul</span> <span class="mi">5</span> <span class="mi">3</span>
<span class="c1"># 15</span>
</code></pre></div>
<p>如果指定了操作(add 或是 mul)以及 2 个数字参数,
则参数将解析到 args 变量中;
然后, 从字典调用函数时,使用这些秋粮和 args.operation ,
最后将其结果分配给 answer 变量;</p>
<p>另外一个使用字典调度的实际案例,
是对许多不同的传入事件作出反应 -- 例如 -- 来自 webhook,
又或是来自 GitHub 的拉取请求事件:</p>
<p>Another practical example of using dictionary dispatch is reacting to many different incoming events - for example - from a webhook, such as pull request events from GitHub:</p>
<div class="highlight"><pre><span></span><code><span class="n">event</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">"action"</span><span class="p">:</span> <span class="s2">"opened"</span><span class="p">,</span>
<span class="s2">"pull_request"</span><span class="p">:</span> <span class="p">{</span>
<span class="s2">"url"</span><span class="p">:</span> <span class="s2">"https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/pulls/2"</span><span class="p">,</span>
<span class="s2">"id"</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="s2">"state"</span><span class="p">:</span> <span class="s2">"open"</span><span class="p">,</span>
<span class="s2">"locked"</span><span class="p">:</span> <span class="kc">False</span><span class="p">,</span>
<span class="s2">"title"</span><span class="p">:</span> <span class="s2">"Update the README with new information."</span><span class="p">,</span>
<span class="s2">"user"</span><span class="p">:</span> <span class="p">{</span>
<span class="s2">"login"</span><span class="p">:</span> <span class="s2">"Codertocat"</span><span class="p">,</span>
<span class="s2">"id"</span><span class="p">:</span> <span class="mi">4</span>
<span class="p">},</span>
<span class="s2">"body"</span><span class="p">:</span> <span class="s2">"This is a pretty simple change that we need to pull into master."</span><span class="p">,</span>
<span class="s2">"sender"</span><span class="p">:</span> <span class="p">{</span>
<span class="s2">"login"</span><span class="p">:</span> <span class="s2">"Codertocat"</span><span class="p">,</span>
<span class="s2">"id"</span><span class="p">:</span> <span class="mi">4</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<p>GitHub 拉取事件可以指定许多不同的操作,
例如: assigned,edited, labeled, 等等;
这里, 我们尝试实现 4 种最常见的字典调度:</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">opened</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Processing with action 'opened': </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
<span class="o">...</span>
<span class="k">def</span> <span class="nf">reopened</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Processing with action 'reopened': </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
<span class="o">...</span>
<span class="k">def</span> <span class="nf">closed</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Processing with action 'closed': </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
<span class="o">...</span>
<span class="k">def</span> <span class="nf">synchronize</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Processing with action 'synchronize': </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
<span class="o">...</span>
<span class="n">actions</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">"opened"</span><span class="p">:</span> <span class="n">opened</span><span class="p">,</span>
<span class="s2">"reopened"</span><span class="p">:</span> <span class="n">reopened</span><span class="p">,</span>
<span class="s2">"closed"</span><span class="p">:</span> <span class="n">closed</span><span class="p">,</span>
<span class="s2">"synchronize"</span><span class="p">:</span> <span class="n">synchronize</span><span class="p">,</span>
<span class="p">}</span>
<span class="n">actions</span><span class="p">[</span><span class="n">event</span><span class="p">[</span><span class="s2">"action"</span><span class="p">]](</span><span class="n">event</span><span class="p">)</span>
<span class="c1"># Processing with action 'opened': {'action': 'opened', 'pull_request': {...}, "body": "...", ... }</span>
</code></pre></div>
<p>我们为每个动作类型定义一个单独的函数,
以便我们可以分别处理每个案例;
在此示例中,我们直接将整个有效载荷传递给所有函数,
但是,我们可以在传递事件载荷之前对其进行操作,
正如前述所示:</p>
<h2 id="_5">访问者模式<a class="headerlink" href="#_5" title="Permanent link">¶</a></h2>
<p>最后, 虽然简单的字典通常足够了,
但是, 如果你需要更加健壮的解决方案, 可以应用 <code>访问者模式</code>:</p>
<div class="highlight"><pre><span></span><code><span class="k">class</span> <span class="nc">Visitor</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">visit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">action</span><span class="p">,</span> <span class="n">payload</span><span class="p">):</span>
<span class="n">method_name</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"visit_</span><span class="si">{</span><span class="n">action</span><span class="si">}</span><span class="s2">"</span>
<span class="n">m</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">method_name</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
<span class="k">if</span> <span class="n">m</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">m</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">default_visit</span>
<span class="k">return</span> <span class="n">m</span><span class="p">(</span><span class="n">payload</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">default_visit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">action</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Default action..."</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">GithubEvaluator</span><span class="p">(</span><span class="n">Visitor</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">visit_opened</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">payload</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Processing with action 'opened': </span><span class="si">{</span><span class="n">payload</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">visit_reopened</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">payload</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Processing with action 'reopened': </span><span class="si">{</span><span class="n">payload</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
<span class="n">e</span> <span class="o">=</span> <span class="n">GithubEvaluator</span><span class="p">()</span>
<span class="n">e</span><span class="o">.</span><span class="n">visit</span><span class="p">(</span><span class="s2">"opened"</span><span class="p">,</span> <span class="n">event</span><span class="p">)</span>
<span class="c1"># Processing with action 'opened': {'action': 'opened', 'pull_request': {...}, "body": "...", ... }</span>
</code></pre></div>
<p>该东西方是通过首先构建一个具有访问功能的 Visitor 父类来实现的;
此函数自动调用名称匹配模式为 <code>visit_<ACTION></code> 的函数;
然后,
这些单独的功能由子类实现, 其中每个功能本质上都充当了 "字典" 里其中一个 "键";
最后, 要使用这个模式/类,
嘦调用 visit 方法, 并让类测定调用哪个函数就好;</p>
<h2 id="_6">小结<a class="headerlink" href="#_6" title="Permanent link">¶</a></h2>
<p>避免条件判定是使事情变得简单可靠的方法,
但是, 这并不意味着我们应该尝试将字典分派硬塞到需要条件判定的每段代码中;</p>
<p>其实,这种模式有很好的用例, 比如说非常长的条件语句链;
又如果, 你因为某些原因无法使用不支持 match/case 的 Python 版本;</p>
<p>此外, 字典本身是可以动态改变的,
比如,通过追加键或是更改值(函数),这是普通条件语句无法实现的;</p>
<p>最后, 即便你不想使用字典(表)调度,
熟悉这一模式也是好的,
因为,在某些时候你很可能会遇到使用这一模式的代码,
那时你能看得懂, 就很不错呢. 😉</p>
<h2 id="ps">PS:<a class="headerlink" href="#ps" title="Permanent link">¶</a></h2>
<p>一般都是在对一组相似场景中要进行不同决策时,
需要使用 字典分派,
而且, 直接使用, 比用 访问者模式 的类要来的简洁,
而且也节省内存;</p>
<p>经验中, 唯一要注意的, 就是这组函数, 最好能有统一的参数形式,
否则, 调试起来很容易出问题;</p>
<p>另外, match/case 毕竟是语言级别的内建语法,
比手工用 字典来进行分派要流畅的多,
能用还是多用;</p>ScrapBook 在 M1macOS 上恢复2022-12-13T21:42:00+08:002023-01-06T16:15:24+08:00ZoomQuiettag:blog.zoomquiet.io,2022-12-13:/221213-scrapbook-revert.html<p>ScrapBook/ 长期使用的私人知识仓库核心组件回归</p>
<h2 id="background">Background<a class="headerlink" href="#background" title="Permanent link">¶</a></h2>
<p><img alt="neofetch" src="https://ipic.zoomquiet.top/2022-12-13-zshot%202022-12-14%2000.18.51.jpg"/></p>
<p><a href="https://du.101.camp/2017-11/ff-no-upgrade/">嫑升级 FireFox 到 56 以上 ~ DebugUself with DAMA ;-)</a></p>
<h2 id="problem">Problem<a class="headerlink" href="#problem" title="Permanent link">¶</a></h2>
<p>之前通过不升级 FireFox 继续使用了一段时间,
但是,随着 FireFox 公司的折腾,一不小心就自动升级了;
好在找到了 <strong>WaterFox</strong> ,是的, 人家就是叫这个名字,
明确就是对着干的, 当然,为了生存 <code>水狐</code> 也不得不用了 Chromiun 内核,
导致无法兼容老的基于 <code>XPCOM + XUL</code> 插件;
好在社区给力,及时分离出一个 <code>Waterfox Classic</code> 版本专门干这事儿;</p>
<p><img alt="Waterfox" src="https://ipic.zoomquiet.top/2022-12-13-scrapbook_revert-1.jpeg"/></p>
<p>问题在 M1 macOS 从 12.x 升级到 13.0.1 后, <strong>WaterFox</strong> 全面失效,
窗口无法打开;</p>
<p><img alt="scrapbook_revert" src="https://ipic.zoomquiet.top/2022-12-13-scrapbook_revert-0.jpeg"/></p>
<p>那么,俺通过 ScrapBook 从05年开始, 17年以来收集到的近8万个本地网页资料就无法按照以往的习惯快速使用了...</p>
<p>这是无法承受的.</p>
<h2 id="trace">Trace<a class="headerlink" href="#trace" title="Permanent link">¶</a></h2>
<p>好在 ScrapBook, 虽然使用 XUL 技术构建,但是,对抓到本地的网页管理很简洁:</p>
<ul>
<li>XML 文件记录用户定义的树形关系,并指向具体的本地目录</li>
<li>所有网页以目录形式写入本地硬盘, index.html 为入口,其它原有资源修改访问地址后同目录保存</li>
</ul>
<p>所以, 我可以自行开发类似 ScrapBook 的管理/查阅界面工具来恢复使用;
不过, 这就要一个不可控的时间;</p>
<p>那么, 还有什么方案可以在 M1 macOS 环境中恢复一个老版本的 <code>FireFox</code> 或是可安装 <code>ScrapBook</code> 的 <code>WaterFox</code> 呢?</p>
<p>既然 macOS 对软件安装有很多限制,那么通过 Linux 环境来恢复对应浏览器界面应该可以,
只不过, <code>ScrapBook</code> 的数据处理有两种方案:</p>
<ul>
<li>放在 macOS 本地, 通过共享目录给虚拟机中的浏览器访问<ul>
<li>然后, 通过 <code>VNC</code> 之类远程桌面,在 macOS 桌面上使用本地其它 OS 中的浏览器访问</li>
</ul>
</li>
<li>放在 macOS 本地, 通过 <code>shellFS</code> 挂载到其它 Linux 主机中提供给浏览器访问<ul>
<li>然后, 通过 <code>VNC</code> 之类远程桌面,在 macOS 桌面上使用远程浏览器访问历史网页</li>
</ul>
</li>
</ul>
<p>很明显, 后一种方案依赖其它主机, 这将导致俺在移动时, 无法恢复 <code>ScrapBook</code> 仓库的资料使用;</p>
<p>那么就用第一种</p>
<h3 id="multipass">Multipass<a class="headerlink" href="#multipass" title="Permanent link">¶</a></h3>
<p>以往习惯的虚拟主机管理器是 <code>VirtualBox</code> ,
可以至今 M1 版本还是实验状态,尝试了一下根本无法合理安装起来一个 Ubuntu 系统;</p>
<p>对比了其它 macOS 中的虚拟主机控制方式; Docker 首先放弃,收费方案也略过;</p>
<p>发现 Ubuntu 官方推出的新方案支持 M1 环境,</p>
<p>这就是 Multipass, 一切看起来很好, 也快速安装好了一个 Ubuntu 22.04 服务器版本;
问题是, 可以进入 shell ,但是,无法访问互联网,
这也就意味着,无法安装新软件;</p>
<p>折腾了很久, 甚至于动用 ChatGPT 联调, 也不行;</p>
<h3 id="utm">UTM<a class="headerlink" href="#utm" title="Permanent link">¶</a></h3>
<p>一开始尝试过,没安装成功,
再次尝试,找到对应视频, 才发现,用错了镜像,使用 arm 版本桌面镜像后,
顺利启动;
在 UTM 配置界面中,根据 <code>ifconfig</code> 选对 USB 外置网络连接后,</p>
<p><img alt="UTM" src="https://ipic.zoomquiet.top/2022-12-13-zshot%202022-12-14%2000.29.38.jpg"/></p>
<p>也能访问互联网, 并切换了国内镜像,
没想到,根据有关文档安装老版本 FireFox 时, 发现没有对应 arm 版本的包;
两样, 也没找到 <code>WaterFox</code> arm 版本的 Linux 安装包;</p>
<p>这就尴尬了,
忘记了 M1 的虚拟机,不可能安装其它芯片方案的系统;
这导致对应软件安装依然不简单...</p>
<h2 id="revert">revert<a class="headerlink" href="#revert" title="Permanent link">¶</a></h2>
<p>终于醒悟过来后, 去 <code>WaterFox</code> 官方看了一下, 发现有升级,
顺利安装 <code>Waterfox Classic</code> 22.11 版本, 替代有问题的 22.10 版本</p>
<p><img alt="Waterfox" src="https://ipic.zoomquiet.top/2022-12-13-scrapbook_revert-2.jpeg"/></p>
<p>一切恢复;</p>
<p>不过,隐患依然存在,
想永远可以自由的以 <code>ScrapBook</code> 的形式继续使用自己积累的知识仓库,
还是要自立更生, 拥有自己完全控制的对应软件呢.</p>
<h3 id="ps">PS:<a class="headerlink" href="#ps" title="Permanent link">¶</a></h3>
<blockquote>
<p>为什么无法放弃 ScrapBook ?</p>
</blockquote>
<p>因为已经形成了效能习惯:</p>
<ul>
<li>看到合适网页,先用 ScrapBook 抓到本地, 这样即便原网页消失,资料也在硬盘中了<ul>
<li>抽空精读, 并标记重点, 然后, 组织到合理的分类树中</li>
<li>需要时, 根据任务快速重组/增补对应知识点配置网页资料</li>
</ul>
</li>
<li>同时, 通过自己编写的 Python 脚本,可以快速将各种分类的 SrapBook 资料分享到网络中<ul>
<li><a href="https://zoomquiet.io/collection.html">ZoomQuiet.io -> collection {by gen4dot2htm.py vv.190718 at:190911 18:13:08,805091}</a></li>
<li>而且可以给每个网页追加自定页尾声明</li>
</ul>
</li>
</ul>
<h2 id="refer">refer.<a class="headerlink" href="#refer" title="Permanent link">¶</a></h2>
<ul>
<li><a href="https://zh.m.wikipedia.org/zh-hans/Apple_M1">Apple M1 - 维基百科,自由的百科全书</a></li>
<li><a href="http://www.xuldev.org/scrapbook/">ScrapBook :: Firefox Extension</a></li>
<li><a href="https://multipass.run/docs/installing-on-macos">How to install Multipass on macOS | Multipass documentation</a></li>
<li><a href="https://www.youtube.com/watch?v=1WWj6qoWhJw">How To Install Ubuntu 22.04 On M1 Mac || RUN Ubuntu Linux On ANY Mac W/ Apple Silicon - YouTube</a><ul>
<li><a href="https://gist.github.com/stephenharris/90bb468bf80e7f7b02e8b8afe694de4f">Installing a particular version of firefox on Linux.</a></li>
</ul>
</li>
<li><a href="https://classic.waterfox.net/">Waterfox Classic | Waterfox Classic</a></li>
<li>...</li>
</ul>
<h2 id="logging">logging<a class="headerlink" href="#logging" title="Permanent link">¶</a></h2>
<ul>
<li>221213 zoomquiet 终于解决<ul>
<li>230106 重新发布</li>
</ul>
</li>
<li>221111 zoomquiet M1macOS 升级后再次无法使用</li>
<li>2017 zoomquiet 撞上 FireFox 放弃所有 XUL 扩展问题</li>
<li>2005 zoomquiet init. scrapbook in FireFox</li>
</ul>How to install Leo under M1 chip macOS 12.*2022-05-29T00:00:00+08:002022-05-29T23:25:31+08:00Zoom.Quiettag:blog.zoomquiet.io,2022-05-29:/leo-install-m1mac-summary.html
<h2 id="background">Background<a class="headerlink" href="#background" title="Permanent link">¶</a></h2>
<p>base <a href="http://leoeditor.com/installing.html#installing-leo-on-macos-10-7-lion-and-later">Installing Leo — Leo 6.6.2 documentation</a>
can not installing Leo on MacOs 12.4 with M1max chip:</p>
<p><img alt="screenfetch" src="https://ipic.zoomquiet.top/2022-05-29-220529-screenfetch.jpg"/></p>
<h2 id="upgrade">Upgrade<a class="headerlink" href="#upgrade" title="Permanent link">¶</a></h2>
<blockquote>
<p>only for M1 chip Mac Book Pro</p>
</blockquote>
<p>base ARM support Homebrew, check version:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>abrew<span class="w"> </span>--version
Homebrew<span class="w"> </span><span class="m">3</span>.4.11
Homebrew/homebrew-core<span class="w"> </span><span class="o">(</span>git<span class="w"> </span>revision<span class="w"> </span>b8f03171990<span class="p">;</span><span class="w"> </span>last<span class="w"> </span>commit<span class="w"> </span><span class="m">2022</span>-05-27<span class="o">)</span>
Homebrew …</code></pre></div>
<h2 id="background">Background<a class="headerlink" href="#background" title="Permanent link">¶</a></h2>
<p>base <a href="http://leoeditor.com/installing.html#installing-leo-on-macos-10-7-lion-and-later">Installing Leo — Leo 6.6.2 documentation</a>
can not installing Leo on MacOs 12.4 with M1max chip:</p>
<p><img alt="screenfetch" src="https://ipic.zoomquiet.top/2022-05-29-220529-screenfetch.jpg"/></p>
<h2 id="upgrade">Upgrade<a class="headerlink" href="#upgrade" title="Permanent link">¶</a></h2>
<blockquote>
<p>only for M1 chip Mac Book Pro</p>
</blockquote>
<p>base ARM support Homebrew, check version:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>abrew<span class="w"> </span>--version
Homebrew<span class="w"> </span><span class="m">3</span>.4.11
Homebrew/homebrew-core<span class="w"> </span><span class="o">(</span>git<span class="w"> </span>revision<span class="w"> </span>b8f03171990<span class="p">;</span><span class="w"> </span>last<span class="w"> </span>commit<span class="w"> </span><span class="m">2022</span>-05-27<span class="o">)</span>
Homebrew/homebrew-cask<span class="w"> </span><span class="o">(</span>git<span class="w"> </span>revision<span class="w"> </span>7cd05aa248<span class="p">;</span><span class="w"> </span>last<span class="w"> </span>commit<span class="w"> </span><span class="m">2022</span>-05-27<span class="o">)</span>
</code></pre></div>
<blockquote>
<p>PS: </p>
</blockquote>
<p>base alias for Intel and ARM verions (<code>~/.bash_profile</code>):</p>
<div class="highlight"><pre><span></span><code>alias abrew='/opt/homebrew/bin/brew '
alias ibrew='/usr/local/bin/brew '
</code></pre></div>
<p>install moniconda:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>abrew<span class="w"> </span>install<span class="w"> </span>miniconda
</code></pre></div>
<p>initialization it:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>conda<span class="w"> </span>init<span class="w"> </span>bash
</code></pre></div>
<p>SEE: <a href="https://docs.conda.io/projects/conda/en/latest/dev-guide/deep-dive-activation.html">Deep dive: conda init and activate — conda 4.13.0.post1+0adcd595 documentation</a></p>
<p>will <code>~/.bash_profile</code> fund like:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># >>> conda initialize >>></span>
<span class="c1"># !! Contents within this block are managed by 'conda init' !!</span>
<span class="n">__conda_setup</span><span class="o">=</span><span class="s2">"$('/opt/homebrew/Caskroom/miniconda/base/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"</span>
<span class="k">if</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="o">$</span><span class="err">?</span><span class="w"> </span><span class="o">-</span><span class="n">eq</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">];</span><span class="w"> </span><span class="n">then</span>
<span class="w"> </span><span class="n">eval</span><span class="w"> </span><span class="s2">"$__conda_setup"</span>
<span class="k">else</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="o">-</span><span class="n">f</span><span class="w"> </span><span class="s2">"/opt/homebrew/Caskroom/miniconda/base/etc/profile.d/conda.sh"</span><span class="w"> </span><span class="p">];</span><span class="w"> </span><span class="n">then</span>
<span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="s2">"/opt/homebrew/Caskroom/miniconda/base/etc/profile.d/conda.sh"</span>
<span class="w"> </span><span class="k">else</span>
<span class="w"> </span><span class="k">export</span><span class="w"> </span><span class="n">PATH</span><span class="o">=</span><span class="s2">"/opt/homebrew/Caskroom/miniconda/base/bin:$PATH"</span>
<span class="w"> </span><span class="n">fi</span>
<span class="n">fi</span>
<span class="n">unset</span><span class="w"> </span><span class="n">__conda_setup</span>
<span class="c1"># <<< conda initialize <<<</span>
</code></pre></div>
<p>install PyQt:</p>
<div class="highlight"><pre><span></span><code><span class="n">$</span><span class="w"> </span><span class="n">abrew</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">PyQt</span><span class="mi">@5</span>
</code></pre></div>
<p>base <code>conda info</code> check miniconda is working;
and create Leo special environment:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>conda<span class="w"> </span>create<span class="w"> </span>-n<span class="w"> </span>leo3912<span class="w"> </span><span class="nv">python</span><span class="o">=</span><span class="m">3</span>.9.12
</code></pre></div>
<p>check result:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>conda<span class="w"> </span>env<span class="w"> </span>list
conda<span class="w"> </span>env<span class="w"> </span>list
/opt/homebrew/Caskroom/miniconda/base/lib/python3.9/site-packages/_distutils_hack/__init__.py:30:<span class="w"> </span>UserWarning:<span class="w"> </span>Setuptools<span class="w"> </span>is<span class="w"> </span>replacing<span class="w"> </span>distutils.
<span class="w"> </span>warnings.warn<span class="o">(</span><span class="s2">"Setuptools is replacing distutils."</span><span class="o">)</span>
<span class="c1"># conda environments:</span>
<span class="c1">#</span>
base<span class="w"> </span>*<span class="w"> </span>/opt/homebrew/Caskroom/miniconda/base
leo3912<span class="w"> </span>/opt/homebrew/Caskroom/miniconda/base/envs/leo3912
</code></pre></div>
<p>copy PyQt packets from brew to miniconda:</p>
<p>such as:
+ from <code>/opt/homebrew/Cellar/pyqt@5/5.15.6/lib/python3.9/site-packages/</code>
+ to <code>/opt/homebrew/Caskroom/miniconda/base/envs/leo3912/lib/python3.9/site-packages/</code></p>
<p>need all of them:</p>
<div class="highlight"><pre><span></span><code>PyQt3D-5.15.5.dist-info
PyQt5
PyQt5-5.15.6.dist-info
PyQt5_sip-12.9.0-py3.9.egg-info
PyQtChart-5.15.5.dist-info
PyQtDataVisualization-5.15.5.dist-info
PyQtNetworkAuth-5.15.5.dist-info
PyQtPurchasing-5.15.5.dist-info
</code></pre></div>
<p>and download Leo Source code release from <a href="https://github.com/leo-editor/leo-editor/releases/latest">Latest</a> </p>
<p>deploy into right path, such as <code>/opt/bin/leo</code></p>
<p>and into conda environment install leo:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>conda<span class="w"> </span>activate<span class="w"> </span>leo3912
$<span class="w"> </span>pip<span class="w"> </span>install<span class="w"> </span>leo
</code></pre></div>
<p>will got some error, but is ok, can suto install these:</p>
<ul>
<li>Successfully installed Jinja2-3.1.2 MarkupSafe-2.1.1 alabaster-0.7.12 astroid-2.11.5 attrs-21.4.0 babel-2.10.1 dialite-0.5.3 dill-0.3.5.1 docutils-0.17.1 fastjsonschema-2.15.3 flexx-0.8.4 future-0.18.2 imagesize-1.3.0 importlib-metadata-4.11.4 isort-5.10.1 jsonschema-4.5.1 jupyter-core-4.10.0 lazy-object-proxy-1.7.1 leo-5.9 mccabe-0.7.0 nbformat-5.4.0 platformdirs-2.5.2 pscript-0.7.7 pyflakes-2.4.0 pylint-2.13.9 pyrsistent-0.18.1 pytz-2022.1 six-1.16.0 snowballstemmer-2.2.0 sphinx-4.5.0 sphinxcontrib-applehelp-1.0.2 sphinxcontrib-devhelp-1.0.2 sphinxcontrib-htmlhelp-2.0.0 sphinxcontrib-jsmath-1.0.1 sphinxcontrib-qthelp-1.0.3 sphinxcontrib-serializinghtml-1.1.5 tomli-2.0.1 tornado-6.1 traitlets-5.2.1.post0 typing-extensions-4.2.0 webruntime-0.5.8 wrapt-1.14.1 zipp-3.8.0</li>
</ul>
<p>notice: for some reason, installed is leo-5.9, one old verion;
so means ,
now under conda environment need can call leo with hand deploy verion:</p>
<div class="highlight"><pre><span></span><code><span class="o">(</span><span class="nt">conda</span><span class="o">:</span><span class="w"> </span><span class="nt">leo3912</span><span class="o">)</span>
<span class="o">$</span><span class="w"> </span><span class="nt">python</span><span class="w"> </span><span class="o">/</span><span class="nt">opt</span><span class="o">/</span><span class="nt">bin</span><span class="o">/</span><span class="nt">leo</span><span class="o">/</span><span class="nt">launchLeo</span><span class="p">.</span><span class="nc">py</span>
<span class="nt">setting</span><span class="w"> </span><span class="nt">leoID</span><span class="w"> </span><span class="nt">from</span><span class="w"> </span><span class="nt">os</span><span class="p">.</span><span class="nc">getenv</span><span class="o">(</span><span class="s1">'USER'</span><span class="o">):</span><span class="w"> </span><span class="s1">'zoomq'</span>
<span class="nt">PYLINTHOME</span><span class="w"> </span><span class="nt">is</span><span class="w"> </span><span class="nt">now</span><span class="w"> </span><span class="s1">'/Users/zoomq/Library/Caches/pylint'</span><span class="w"> </span><span class="nt">but</span><span class="w"> </span><span class="nt">obsolescent</span><span class="w"> </span><span class="s1">'/Users/zoomq/.pylint.d'</span><span class="w"> </span><span class="nt">is</span><span class="w"> </span><span class="nt">found</span><span class="o">;</span><span class="w"> </span><span class="nt">you</span><span class="w"> </span><span class="nt">can</span><span class="w"> </span><span class="nt">safely</span><span class="w"> </span><span class="nt">remove</span><span class="w"> </span><span class="nt">the</span><span class="w"> </span><span class="nt">latter</span>
<span class="nt">duplicate</span><span class="o">,</span><span class="w"> </span><span class="o">(</span><span class="nt">not</span><span class="w"> </span><span class="nt">conflicting</span><span class="o">)</span><span class="w"> </span><span class="nt">key</span><span class="w"> </span><span class="nt">bindings</span><span class="w"> </span><span class="nt">in</span><span class="w"> </span><span class="nt">myLeoSettings</span><span class="p">.</span><span class="nc">leo</span>
<span class="nt">all</span><span class="w"> </span><span class="nt">Alt</span><span class="o">+)</span><span class="w"> </span><span class="nt">move-past-close</span>
<span class="nt">all</span><span class="w"> </span><span class="nt">Alt</span><span class="o">+)</span><span class="w"> </span><span class="nt">move-past-close</span>
<span class="nt">duplicate</span><span class="o">,</span><span class="w"> </span><span class="o">(</span><span class="nt">not</span><span class="w"> </span><span class="nt">conflicting</span><span class="o">)</span><span class="w"> </span><span class="nt">key</span><span class="w"> </span><span class="nt">bindings</span><span class="w"> </span><span class="nt">in</span><span class="w"> </span><span class="nt">myLeoSettings</span><span class="p">.</span><span class="nc">leo</span>
<span class="nt">all</span><span class="w"> </span><span class="nt">Alt</span><span class="o">+</span><span class="err">}</span><span class="w"> </span><span class="nt">forward-paragraph</span>
<span class="nt">all</span><span class="w"> </span><span class="nt">Alt</span><span class="o">+</span><span class="err">}</span><span class="w"> </span><span class="nt">forward-paragraph-extend-selection</span>
<span class="nt">duplicate</span><span class="o">,</span><span class="w"> </span><span class="o">(</span><span class="nt">not</span><span class="w"> </span><span class="nt">conflicting</span><span class="o">)</span><span class="w"> </span><span class="nt">key</span><span class="w"> </span><span class="nt">bindings</span><span class="w"> </span><span class="nt">in</span><span class="w"> </span><span class="nt">myLeoSettings</span><span class="p">.</span><span class="nc">leo</span>
<span class="nt">all</span><span class="w"> </span><span class="nt">Ctrl</span><span class="o">+(</span><span class="w"> </span><span class="nt">add-comments</span>
<span class="nt">all</span><span class="w"> </span><span class="nt">Ctrl</span><span class="o">+(</span><span class="w"> </span><span class="nt">add-comments</span>
<span class="nt">duplicate</span><span class="o">,</span><span class="w"> </span><span class="o">(</span><span class="nt">not</span><span class="w"> </span><span class="nt">conflicting</span><span class="o">)</span><span class="w"> </span><span class="nt">key</span><span class="w"> </span><span class="nt">bindings</span><span class="w"> </span><span class="nt">in</span><span class="w"> </span><span class="nt">myLeoSettings</span><span class="p">.</span><span class="nc">leo</span>
<span class="nt">all</span><span class="w"> </span><span class="nt">Ctrl</span><span class="o">+)</span><span class="w"> </span><span class="nt">delete-comments</span>
<span class="nt">all</span><span class="w"> </span><span class="nt">Ctrl</span><span class="o">+)</span><span class="w"> </span><span class="nt">delete-comments</span>
<span class="nt">all</span><span class="w"> </span><span class="nt">Ctrl</span><span class="o">+)</span><span class="w"> </span><span class="nt">delete-comments</span>
<span class="nt">duplicate</span><span class="o">,</span><span class="w"> </span><span class="o">(</span><span class="nt">not</span><span class="w"> </span><span class="nt">conflicting</span><span class="o">)</span><span class="w"> </span><span class="nt">key</span><span class="w"> </span><span class="nt">bindings</span><span class="w"> </span><span class="nt">in</span><span class="w"> </span><span class="nt">myLeoSettings</span><span class="p">.</span><span class="nc">leo</span>
<span class="nt">all</span><span class="w"> </span><span class="nt">Ctrl</span><span class="o">+</span><span class="p">{</span><span class="w"> </span><span class="err">promote</span>
<span class="err">all</span><span class="w"> </span><span class="err">Ctrl+{</span><span class="w"> </span><span class="err">promote</span>
<span class="err">duplicate,</span><span class="w"> </span><span class="err">(not</span><span class="w"> </span><span class="err">conflicting)</span><span class="w"> </span><span class="err">key</span><span class="w"> </span><span class="err">bindings</span><span class="w"> </span><span class="err">in</span><span class="w"> </span><span class="err">myLeoSettings.leo</span>
<span class="err">all</span><span class="w"> </span><span class="err">Ctrl+</span><span class="p">}</span><span class="w"> </span><span class="nt">demote</span>
<span class="nt">all</span><span class="w"> </span><span class="nt">Ctrl</span><span class="o">+</span><span class="err">}</span><span class="w"> </span><span class="nt">demote</span>
<span class="nt">Leo</span><span class="w"> </span><span class="nt">6</span><span class="p">.</span><span class="nc">6</span><span class="p">.</span><span class="nc">2</span>
<span class="nt">Python</span><span class="w"> </span><span class="nt">3</span><span class="p">.</span><span class="nc">9</span><span class="p">.</span><span class="nc">12</span><span class="o">,</span><span class="w"> </span><span class="nt">PyQt</span><span class="w"> </span><span class="nt">version</span><span class="w"> </span><span class="nt">5</span><span class="p">.</span><span class="nc">15</span><span class="p">.</span><span class="nc">3</span>
<span class="nt">darwin</span>
<span class="o">...</span>
</code></pre></div>
<p><img alt="Leo 6.6.2" src="https://ipic.zoomquiet.top/2022-05-29-zshot%202022-05-29%2022.10.10-1.jpg"/></p>
<p>suggest define alias for daily,
<code>~/.bash_profile</code> add:</p>
<div class="highlight"><pre><span></span><code>alias leo6lanch="python /opt/bin/leo/launchLeo.py >> /dev/null 2>&1 &"
</code></pre></div>
<p>finally start-up leo need two commands:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>conda<span class="w"> </span>activate<span class="w"> </span>leo3912
$<span class="w"> </span>leo6lanch
</code></pre></div>
<h2 id="summary">Summary<a class="headerlink" href="#summary" title="Permanent link">¶</a></h2>
<blockquote>
<p>only for macOS 12.* with M1 chip</p>
</blockquote>
<ul>
<li>base installed arm Homebrew, and miniconda</li>
<li>usage brew install Qt and PyQt</li>
<li>usage conda create environment for Leo</li>
<li>ATTENTION:<ul>
<li>copy PyQt packets from brew to conda an first</li>
<li>so usage pip install leo in auto</li>
</ul>
</li>
<li>download latest Leo from github</li>
<li>finally from conda environment's Python call the <code>launchLeo.py</code></li>
</ul>
<h2 id="logging">logging<a class="headerlink" href="#logging" title="Permanent link">¶</a></h2>
<ul>
<li>220529 publish as blog</li>
<li>220528 miniconda + abrew can work</li>
<li>220527 error mix, had to try again</li>
<li>220506 try again, not fix yet</li>
<li>220401 try re-install PyENV, not work</li>
<li>211113 jump into M1max , fund some chaos</li>
</ul>M1macOS 下 Leo 复活故事2022-05-28T00:00:00+08:002022-05-29T22:28:32+08:00Zoom.Quiettag:blog.zoomquiet.io,2022-05-28:/leo-install-m1mac-story.html
<h2 id="background">Background<a class="headerlink" href="#background" title="Permanent link">¶</a></h2>
<blockquote>
<p>背景</p>
</blockquote>
<p>Leo 是文学化编辑环境, 由 EKR/令老爷子 单人为主长期维护的优秀开发/编撰/思考/...环境;
从 05 年上手以来, 一直在各种场 …</p>
<h2 id="background">Background<a class="headerlink" href="#background" title="Permanent link">¶</a></h2>
<blockquote>
<p>背景</p>
</blockquote>
<p>Leo 是文学化编辑环境, 由 EKR/令老爷子 单人为主长期维护的优秀开发/编撰/思考/...环境;
从 05 年上手以来, 一直在各种场景中欢快的使用,
历经 WindownsNT/Ubuntu/MAC 到现在的 macOS 12.* ,
可以说, 依托 Python 的跨平台属性, 一直能相对平滑的迁移;</p>
<p>比如: <a href="https://blog.zoomquiet.io/leo5theme.html">Leo 5.2 theme custom</a></p>
<p>事实上官方文档中: <a href="http://leoeditor.com/installing.html#installing-leo-on-macos-10-7-lion-and-later">Installing Leo — Leo 6.6.2 documentation</a> ~ Installing Leo on MacOs 10.7 (Lion) 部分其实就是俺的笔记转化而成的.</p>
<p>为解决本地开发测试, 并尽可能复用运行时到相似的工程中, 以往选择的管理工具是 <a href="https://github.com/pyenv/pyenv">pyenv/pyenv: Simple Python version management</a></p>
<p>参考:<a href="https://testdriven.io/blog/python-environments/">Modern Python Environments - dependency and workspace management | TestDriven.io</a></p>
<p><img alt="Modern Python Environments" src="https://ipic.zoomquiet.top/2022-05-29-PyEnvironments-vs.jpg"/></p>
<p>以往形成的习惯是:</p>
<ul>
<li>用 PyENV 安装不同版本 Python 运行时, 毕竟不同工程部署在不同目标主机中, 对 Python 版本依赖不同</li>
<li>基于 PyENV 的自动绑定机制, 在对应目录中通过指令 <code>pyenv local [指定运行时别名]</code> <ul>
<li>就可以记忆绑定关系, 之后嘦进入相关目录, 将自动完成运行时切换</li>
<li>不必须象其它工具要人工明确运行激活指令</li>
</ul>
</li>
<li>进入对应环境后, 使用 pip 进行标准模块依赖管理</li>
</ul>
<p>整体上可以达成效果:</p>
<ul>
<li>本地和生产环境能部署相同 PyENV 环境</li>
<li>支持不同版本 Python 运行时</li>
<li>支持不同项目有自己的模块依赖树, 和其它工程隔离</li>
<li>支持不同工程, 如果领域接近, 可以绑定其它项目的 PyENV 环境, 节省相同模块的反复安装</li>
<li>...即: Python 运行时版本/项目目录/工程依赖 三者能相对独立配置/管理<ul>
<li>而且, 值得强调的是, 对于配置好的环境, cd 进入时, 自动完成切换</li>
<li>同时, 所有定制运行环境, 统一安装在指定目录中, 和工程目录无关, 不必专门进行 git 忽略配置</li>
</ul>
</li>
</ul>
<h2 id="troubles">Troubles<a class="headerlink" href="#troubles" title="Permanent link">¶</a></h2>
<blockquote>
<p>问题</p>
</blockquote>
<p>不过, 在今年初升级硬件为芯片为 M1max 全新 MBP 后, 就一直有问题:</p>
<p>参考: <a href="https://blog.zoomquiet.io/211114m1max-re-inti-mbp">如何安定进入 M1maxMBP / 是也乎( ̄▽ ̄) / ZoomQuiet.io</a></p>
<p>虽然当时幸运的使用官方迁移工具, 将几乎 94.2% 的环境和数据都自动迁移成功;
由于底层芯片不同, 以往 Python 本地运行时环境虽然能用,
但是, 无法进一步安装新版本 Python 运行时, 以及升级 Leo 到最新版本...</p>
<p>具体的:</p>
<ul>
<li>原先在 Intel 芯片中安装/配置好的 PyENV 环境可以运行<ul>
<li>但是, 无法安装新版本 Python 环境</li>
<li>也无法正常使用对应环境中的 pip 安装新模块</li>
</ul>
</li>
<li>原先在 Intel 芯片中安装/配置好的 miniconda 环境可以运行<ul>
<li>但是, <code>conda info</code> 报错</li>
</ul>
</li>
<li>..感觉只有一组很小的 snap 可以使用, 已经不是两个完备可控的 Python 运行时管理环境了</li>
</ul>
<h2 id="goal">Goal<a class="headerlink" href="#goal" title="Permanent link">¶</a></h2>
<blockquote>
<p>目标</p>
</blockquote>
<p>恢复本地 Python 环境的控制:</p>
<ul>
<li>可以自如安装多种版本 Python 运行时</li>
<li>可以针对不同工程绑定不同模块依赖树, 当然, 也可以复用相同的</li>
<li>可以安装运行最新 Leo 版本<ul>
<li>当前可用是 5.9-b2</li>
<li>官方已经是 6.6.2 了</li>
</ul>
</li>
</ul>
<h2 id="tracing">Tracing<a class="headerlink" href="#tracing" title="Permanent link">¶</a></h2>
<blockquote>
<p>探索</p>
</blockquote>
<p>当前环境:</p>
<p><img alt="screenfetch" src="https://ipic.zoomquiet.top/2022-05-29-220529-screenfetch.jpg"/></p>
<h3 id="pyenv">尝试 PyENV<a class="headerlink" href="#pyenv" title="Permanent link">¶</a></h3>
<ul>
<li>先在 <code>~/.bash_profile</code> 中注释掉所有 PyENV 相关的配置,</li>
<li>将 <code>~/.pyenv</code> 移动为 <code>~/_pyenv</code></li>
<li>根据官方指引: <a href="https://github.com/pyenv/pyenv">pyenv/pyenv: Simple Python version management</a> 重新安装<ul>
<li>而且事先根据 <a href="https://github.com/pyenv/pyenv/wiki#suggested-build-environment">Home · pyenv/pyenv Wiki</a> 的建议</li>
<li>重新安装了 Python 编译依赖</li>
</ul>
</li>
</ul>
<p>一切正常, 其实依赖通过 brew 安装的 python@3.9 完成自举</p>
<div class="highlight"><pre><span></span><code>Python 3.9.8 (main, Nov 10 2021, 03:55:42)
[Clang 13.0.0 (clang-1300.0.29.3)] on darwin
</code></pre></div>
<p>可惜, 尝试通过 <code>pyenv install</code> 指令来安装其它版本 Python 环境,
都撞到编译失败, 反复探索, 网上给的招儿都用过, 还是无法解决.</p>
<h3 id="miniconda">尝试 miniconda<a class="headerlink" href="#miniconda" title="Permanent link">¶</a></h3>
<blockquote>
<p>怀疑 PyENV 准备的编译脚本都是针对 Intel 背景的</p>
</blockquote>
<p>所以, 重新将目光投向 Anaconda, 要知道这个项目已经不仅仅可以管理 Python 环境, 而且其它各种运行时环境都可以管理, 包含 rust/haskell/... 都可以通过 conda 指令一致性部署,
而且事先经过不同平台的针对性预编译, 不用在本地折腾, 直接下载, 展开就可用;</p>
<p>而且, 进入 conda 运行时环境后, 可以继续用 conda 指令安装相关模块, 也可以用 pip 来从 PyPI 下载安装...</p>
<p>唯一不如 PyENV 的就是 conda 环境, 必须手工激活, 无法自动绑定;</p>
<p>之前 miniconda 是手工安装的, 现在已经有全新 arm 版本 brew 环境了,
参考: <a href="https://sspai.com/post/63935#!">在 M1 芯片 Mac 上使用 Homebrew - 少数派</a></p>
<p>标准安装:</p>
<div class="highlight"><pre><span></span><code>abrew install miniconda
</code></pre></div>
<p>因为进行了多 homebrew 环境配置:</p>
<ul>
<li>ibrew 指向旧系统迁移过来的 Intel 版本 homebrew</li>
<li>abrew 指向全新安装的 ARM 版本 homebrew</li>
</ul>
<p>然后, 就可以探查当前支持那些 Python 版本了:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>conda<span class="w"> </span>search<span class="w"> </span><span class="s2">"^Python</span>$<span class="s2">"</span>
Loading<span class="w"> </span>channels:<span class="w"> </span><span class="k">done</span>
<span class="c1"># Name Version Build Channel</span>
python<span class="w"> </span><span class="m">3</span>.8.11<span class="w"> </span>hbdb9e5c_5<span class="w"> </span>pkgs/main
python<span class="w"> </span><span class="m">3</span>.8.13<span class="w"> </span>hbdb9e5c_0<span class="w"> </span>pkgs/main
python<span class="w"> </span><span class="m">3</span>.9.6<span class="w"> </span>hc70090a_5<span class="w"> </span>pkgs/main
python<span class="w"> </span><span class="m">3</span>.9.7<span class="w"> </span>hc70090a_1<span class="w"> </span>pkgs/main
python<span class="w"> </span><span class="m">3</span>.9.11<span class="w"> </span>hbdb9e5c_1<span class="w"> </span>pkgs/main
python<span class="w"> </span><span class="m">3</span>.9.11<span class="w"> </span>hbdb9e5c_2<span class="w"> </span>pkgs/main
python<span class="w"> </span><span class="m">3</span>.9.12<span class="w"> </span>hbdb9e5c_0<span class="w"> </span>pkgs/main
python<span class="w"> </span><span class="m">3</span>.10.0<span class="w"> </span>hbdb9e5c_1<span class="w"> </span>pkgs/main
python<span class="w"> </span><span class="m">3</span>.10.0<span class="w"> </span>hbdb9e5c_2<span class="w"> </span>pkgs/main
python<span class="w"> </span><span class="m">3</span>.10.0<span class="w"> </span>hbdb9e5c_3<span class="w"> </span>pkgs/main
python<span class="w"> </span><span class="m">3</span>.10.0<span class="w"> </span>hbdb9e5c_5<span class="w"> </span>pkgs/main
python<span class="w"> </span><span class="m">3</span>.10.3<span class="w"> </span>hbdb9e5c_5<span class="w"> </span>pkgs/main
python<span class="w"> </span><span class="m">3</span>.10.4<span class="w"> </span>hbdb9e5c_0<span class="w"> </span>pkgs/main
</code></pre></div>
<p>安装一个 Leo 专用的环境:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>conde<span class="w"> </span>create<span class="w"> </span>-n<span class="w"> </span>leo3811<span class="w"> </span><span class="nv">python</span><span class="o">=</span><span class="m">3</span>.8.11
</code></pre></div>
<p>通过指令进入:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>conda<span class="w"> </span>activate<span class="w"> </span>leo3811
</code></pre></div>
<p>通过事先安装 <code>pip_search</code> 可以搜索出配置的PyPI 镜像是否包含 Leo:</p>
<p><img alt="pip_search" src="https://ipic.zoomquiet.top/2022-05-29-zshot%202022-05-28%2000.07.02.jpg"/></p>
<p>通过 pip 安装 Leo:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>pip<span class="w"> </span>install<span class="w"> </span>leo
</code></pre></div>
<p><img alt="PyQt" src="https://ipic.zoomquiet.top/2022-05-29-zshot%202022-05-28%2000.07.22.jpg"/></p>
<p>过程中, 可以观察到很多编译错误,
但是, 安装脚本足够聪明, 可以逐一版本降低来尝试最终兼容;
安装完成后, 尝试运行:</p>
<div class="highlight"><pre><span></span><code><span class="err">$</span> <span class="n">leo</span>
<span class="n">leoQt</span><span class="o">.</span><span class="n">py</span><span class="p">:</span> <span class="n">can</span> <span class="ow">not</span> <span class="n">fully</span> <span class="kn">import</span> <span class="nn">PyQt5.</span>
<span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="n">File</span> <span class="s2">"/opt/homebrew/Caskroom/miniconda/base/envs/leo3811/lib/python3.8/site-packages/leo/core/leoQt.py"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">55</span><span class="p">,</span> <span class="ow">in</span> <span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="kn">from</span> <span class="nn">PyQt5</span> <span class="kn">import</span> <span class="n">QtCore</span>
<span class="ne">ModuleNotFoundError</span><span class="p">:</span> <span class="n">No</span> <span class="n">module</span> <span class="n">named</span> <span class="s1">'PyQt5.sip'</span>
<span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="n">File</span> <span class="s2">"/opt/homebrew/Caskroom/miniconda/base/envs/leo3811/bin/leo"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">5</span><span class="p">,</span> <span class="ow">in</span> <span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="kn">from</span> <span class="nn">leo.core.runLeo</span> <span class="kn">import</span> <span class="n">run</span>
<span class="n">File</span> <span class="s2">"/opt/homebrew/Caskroom/miniconda/base/envs/leo3811/lib/python3.8/site-packages/leo/core/runLeo.py"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">27</span><span class="p">,</span> <span class="ow">in</span> <span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="n">leoGlobals</span><span class="o">.</span><span class="n">app</span> <span class="o">=</span> <span class="n">leoApp</span><span class="o">.</span><span class="n">LeoApp</span><span class="p">()</span>
<span class="n">File</span> <span class="s2">"/opt/homebrew/Caskroom/miniconda/base/envs/leo3811/lib/python3.8/site-packages/leo/core/leoApp.py"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">334</span><span class="p">,</span> <span class="ow">in</span> <span class="fm">__init__</span>
<span class="kn">import</span> <span class="nn">leo.core.leoFrame</span> <span class="k">as</span> <span class="nn">leoFrame</span>
<span class="n">File</span> <span class="s2">"/opt/homebrew/Caskroom/miniconda/base/envs/leo3811/lib/python3.8/site-packages/leo/core/leoFrame.py"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">13</span><span class="p">,</span> <span class="ow">in</span> <span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="kn">import</span> <span class="nn">leo.core.leoColorizer</span> <span class="k">as</span> <span class="nn">leoColorizer</span>
<span class="n">File</span> <span class="s2">"/opt/homebrew/Caskroom/miniconda/base/envs/leo3811/lib/python3.8/site-packages/leo/core/leoColorizer.py"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">18</span><span class="p">,</span> <span class="ow">in</span> <span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="kn">from</span> <span class="nn">leo.core.leoQt</span> <span class="kn">import</span> <span class="n">Qsci</span><span class="p">,</span> <span class="n">QtGui</span><span class="p">,</span> <span class="n">QtWidgets</span>
<span class="n">File</span> <span class="s2">"/opt/homebrew/Caskroom/miniconda/base/envs/leo3811/lib/python3.8/site-packages/leo/core/leoQt.py"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">88</span><span class="p">,</span> <span class="ow">in</span> <span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="n">qt_version</span> <span class="o">=</span> <span class="n">QtCore</span><span class="o">.</span><span class="n">QT_VERSION_STR</span>
<span class="ne">NameError</span><span class="p">:</span> <span class="n">name</span> <span class="s1">'QtCore'</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">defined</span>
</code></pre></div>
<p>没招, 问 Leo 官方 mailling-list: https://groups.google.com/d/msgid/leo-editor</p>
<p>不久, tbp100.tp@gmail.com 建议:</p>
<blockquote>
<p>this looks like a problem with Qt or PyQt, not leo per se. possibilities:</p>
</blockquote>
<ul>
<li>try to install PyQt6 on its own (without the rest of leo);</li>
<li>try to install an earlier version of PyQt6, if you can figure out which ones are available;</li>
<li>try installing PyQt5 instead of PyQt6 (Leo can use either one); </li>
<li>install python 3.9 and see whether PyQt6 or PyQt5 will install without errors.</li>
</ul>
<h3 id="pyqt">PyQt<a class="headerlink" href="#pyqt" title="Permanent link">¶</a></h3>
<blockquote>
<p>想起来 Qt 是个神奇的东西...</p>
</blockquote>
<p>之前进行桌面开发时, PyQt 就不能简单安装, 对应搜索</p>
<p>国内用户首先要配置 conda 源:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>conda<span class="w"> </span>config<span class="w"> </span>--set<span class="w"> </span>show_channel_urls<span class="w"> </span>yes
</code></pre></div>
<p>生成 <code>~/.condarc</code> 文件后对应修改, 比如俺当前是:</p>
<div class="highlight"><pre><span></span><code><span class="n">auto_activate_base</span><span class="o">:</span><span class="w"> </span><span class="kc">true</span>
<span class="n">report_errors</span><span class="o">:</span><span class="w"> </span><span class="kc">true</span>
<span class="n">show_channel_urls</span><span class="o">:</span><span class="w"> </span><span class="kc">true</span>
<span class="n">channels</span><span class="o">:</span>
<span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">defaults</span>
<span class="n">default_channels</span><span class="o">:</span>
<span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">http</span><span class="o">://</span><span class="n">mirrors</span><span class="o">.</span><span class="na">aliyun</span><span class="o">.</span><span class="na">com</span><span class="sr">/anaconda/pkgs/</span><span class="n">main</span>
<span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">http</span><span class="o">://</span><span class="n">mirrors</span><span class="o">.</span><span class="na">aliyun</span><span class="o">.</span><span class="na">com</span><span class="sr">/anaconda/pkgs/</span><span class="n">r</span>
<span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">http</span><span class="o">://</span><span class="n">mirrors</span><span class="o">.</span><span class="na">aliyun</span><span class="o">.</span><span class="na">com</span><span class="sr">/anaconda/pkgs/</span><span class="n">msys2</span>
<span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">https</span><span class="o">://</span><span class="n">repo</span><span class="o">.</span><span class="na">anaconda</span><span class="o">.</span><span class="na">com</span><span class="sr">/pkgs/</span><span class="n">main</span>
<span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">https</span><span class="o">://</span><span class="n">repo</span><span class="o">.</span><span class="na">anaconda</span><span class="o">.</span><span class="na">com</span><span class="sr">/pkgs/</span><span class="n">r</span>
<span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">https</span><span class="o">://</span><span class="n">repo</span><span class="o">.</span><span class="na">anaconda</span><span class="o">.</span><span class="na">com</span><span class="sr">/pkgs/</span><span class="n">msys2</span>
<span class="n">custom_channels</span><span class="o">:</span>
<span class="w"> </span><span class="n">conda</span><span class="o">-</span><span class="n">forge</span><span class="o">:</span><span class="w"> </span><span class="n">http</span><span class="o">://</span><span class="n">mirrors</span><span class="o">.</span><span class="na">aliyun</span><span class="o">.</span><span class="na">com</span><span class="sr">/anaconda/</span><span class="n">cloud</span>
<span class="w"> </span><span class="n">msys2</span><span class="o">:</span><span class="w"> </span><span class="n">http</span><span class="o">://</span><span class="n">mirrors</span><span class="o">.</span><span class="na">aliyun</span><span class="o">.</span><span class="na">com</span><span class="sr">/anaconda/</span><span class="n">cloud</span>
<span class="w"> </span><span class="n">bioconda</span><span class="o">:</span><span class="w"> </span><span class="n">http</span><span class="o">://</span><span class="n">mirrors</span><span class="o">.</span><span class="na">aliyun</span><span class="o">.</span><span class="na">com</span><span class="sr">/anaconda/</span><span class="n">cloud</span>
<span class="w"> </span><span class="n">menpo</span><span class="o">:</span><span class="w"> </span><span class="n">http</span><span class="o">://</span><span class="n">mirrors</span><span class="o">.</span><span class="na">aliyun</span><span class="o">.</span><span class="na">com</span><span class="sr">/anaconda/</span><span class="n">cloud</span>
<span class="w"> </span><span class="n">pytorch</span><span class="o">:</span><span class="w"> </span><span class="n">http</span><span class="o">://</span><span class="n">mirrors</span><span class="o">.</span><span class="na">aliyun</span><span class="o">.</span><span class="na">com</span><span class="sr">/anaconda/</span><span class="n">cloud</span>
<span class="w"> </span><span class="n">simpleitk</span><span class="o">:</span><span class="w"> </span><span class="n">http</span><span class="o">://</span><span class="n">mirrors</span><span class="o">.</span><span class="na">aliyun</span><span class="o">.</span><span class="na">com</span><span class="sr">/anaconda/</span><span class="n">cloud</span>
</code></pre></div>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="n">conda</span><span class="w"> </span><span class="n">create</span><span class="w"> </span><span class="o">-</span><span class="n">n</span><span class="w"> </span><span class="n">leo3911</span><span class="w"> </span><span class="n">python</span><span class="o">=</span><span class="mf">3.9</span><span class="o">.</span><span class="mi">11</span>
<span class="n">Collecting</span><span class="w"> </span><span class="n">package</span><span class="w"> </span><span class="n">metadata</span><span class="w"> </span><span class="p">(</span><span class="n">current_repodata</span><span class="o">.</span><span class="n">json</span><span class="p">):</span><span class="w"> </span><span class="n">done</span>
<span class="n">Solving</span><span class="w"> </span><span class="n">environment</span><span class="p">:</span><span class="w"> </span><span class="n">failed</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">repodata</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="n">current_repodata</span><span class="o">.</span><span class="n">json</span><span class="p">,</span><span class="w"> </span><span class="n">will</span><span class="w"> </span><span class="n">retry</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">next</span><span class="w"> </span><span class="n">repodata</span><span class="w"> </span><span class="n">source</span><span class="o">.</span>
<span class="n">Collecting</span><span class="w"> </span><span class="n">package</span><span class="w"> </span><span class="n">metadata</span><span class="w"> </span><span class="p">(</span><span class="n">repodata</span><span class="o">.</span><span class="n">json</span><span class="p">):</span><span class="w"> </span><span class="n">done</span>
<span class="n">Solving</span><span class="w"> </span><span class="n">environment</span><span class="p">:</span><span class="w"> </span><span class="n">done</span>
<span class="c1">## Package Plan ##</span>
<span class="w"> </span><span class="n">environment</span><span class="w"> </span><span class="n">location</span><span class="p">:</span><span class="w"> </span><span class="o">/</span><span class="n">opt</span><span class="o">/</span><span class="n">homebrew</span><span class="o">/</span><span class="n">Caskroom</span><span class="o">/</span><span class="n">miniconda</span><span class="o">/</span><span class="n">base</span><span class="o">/</span><span class="n">envs</span><span class="o">/</span><span class="n">leo3911</span>
<span class="w"> </span><span class="n">added</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">updated</span><span class="w"> </span><span class="n">specs</span><span class="p">:</span>
<span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">python</span><span class="o">=</span><span class="mf">3.9</span><span class="o">.</span><span class="mi">11</span>
<span class="n">The</span><span class="w"> </span><span class="n">following</span><span class="w"> </span><span class="n">packages</span><span class="w"> </span><span class="n">will</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">downloaded</span><span class="p">:</span>
<span class="w"> </span><span class="n">package</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">build</span>
<span class="w"> </span><span class="o">---------------------------|-----------------</span>
<span class="w"> </span><span class="n">python</span><span class="o">-</span><span class="mf">3.9</span><span class="o">.</span><span class="mi">11</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">hbdb9e5c_2</span><span class="w"> </span><span class="mf">10.1</span><span class="w"> </span><span class="n">MB</span><span class="w"> </span><span class="n">defaults</span>
<span class="w"> </span><span class="o">------------------------------------------------------------</span>
<span class="w"> </span><span class="n">Total</span><span class="p">:</span><span class="w"> </span><span class="mf">10.1</span><span class="w"> </span><span class="n">MB</span>
<span class="n">The</span><span class="w"> </span><span class="n">following</span><span class="w"> </span><span class="n">NEW</span><span class="w"> </span><span class="n">packages</span><span class="w"> </span><span class="n">will</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">INSTALLED</span><span class="p">:</span>
<span class="w"> </span><span class="n">ca</span><span class="o">-</span><span class="n">certificates</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="n">arm64</span><span class="p">::</span><span class="n">ca</span><span class="o">-</span><span class="n">certificates</span><span class="o">-</span><span class="mf">2022.4</span><span class="o">.</span><span class="mi">26</span><span class="o">-</span><span class="n">hca03da5_0</span>
<span class="w"> </span><span class="n">certifi</span><span class="w"> </span><span class="n">anaconda</span><span class="o">/</span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">noarch</span><span class="p">::</span><span class="n">certifi</span><span class="o">-</span><span class="mf">2020.6</span><span class="o">.</span><span class="mi">20</span><span class="o">-</span><span class="n">pyhd3eb1b0_3</span>
<span class="w"> </span><span class="n">libcxx</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="n">arm64</span><span class="p">::</span><span class="n">libcxx</span><span class="o">-</span><span class="mf">12.0</span><span class="o">.</span><span class="mi">0</span><span class="o">-</span><span class="n">hf6beb65_1</span>
<span class="w"> </span><span class="n">libffi</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="n">arm64</span><span class="p">::</span><span class="n">libffi</span><span class="o">-</span><span class="mf">3.4</span><span class="o">.</span><span class="mi">2</span><span class="o">-</span><span class="n">hc377ac9_2</span>
<span class="w"> </span><span class="n">ncurses</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="n">arm64</span><span class="p">::</span><span class="n">ncurses</span><span class="o">-</span><span class="mf">6.3</span><span class="o">-</span><span class="n">h1a28f6b_2</span>
<span class="w"> </span><span class="n">openssl</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="n">arm64</span><span class="p">::</span><span class="n">openssl</span><span class="o">-</span><span class="mf">1.1</span><span class="o">.</span><span class="mi">1</span><span class="n">o</span><span class="o">-</span><span class="n">h1a28f6b_0</span>
<span class="w"> </span><span class="n">pip</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="n">arm64</span><span class="p">::</span><span class="n">pip</span><span class="o">-</span><span class="mf">21.2</span><span class="o">.</span><span class="mi">4</span><span class="o">-</span><span class="n">py39hca03da5_0</span>
<span class="w"> </span><span class="n">python</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="n">arm64</span><span class="p">::</span><span class="n">python</span><span class="o">-</span><span class="mf">3.9</span><span class="o">.</span><span class="mi">11</span><span class="o">-</span><span class="n">hbdb9e5c_2</span>
<span class="w"> </span><span class="n">readline</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="n">arm64</span><span class="p">::</span><span class="n">readline</span><span class="o">-</span><span class="mf">8.1</span><span class="o">.</span><span class="mi">2</span><span class="o">-</span><span class="n">h1a28f6b_1</span>
<span class="w"> </span><span class="n">setuptools</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="n">arm64</span><span class="p">::</span><span class="n">setuptools</span><span class="o">-</span><span class="mf">61.2</span><span class="o">.</span><span class="mi">0</span><span class="o">-</span><span class="n">py39hca03da5_0</span>
<span class="w"> </span><span class="n">sqlite</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="n">arm64</span><span class="p">::</span><span class="n">sqlite</span><span class="o">-</span><span class="mf">3.38</span><span class="o">.</span><span class="mi">3</span><span class="o">-</span><span class="n">h1058600_0</span>
<span class="w"> </span><span class="n">tk</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="n">arm64</span><span class="p">::</span><span class="n">tk</span><span class="o">-</span><span class="mf">8.6</span><span class="o">.</span><span class="mi">11</span><span class="o">-</span><span class="n">hb8d0fd4_1</span>
<span class="w"> </span><span class="n">tzdata</span><span class="w"> </span><span class="n">anaconda</span><span class="o">/</span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">noarch</span><span class="p">::</span><span class="n">tzdata</span><span class="o">-</span><span class="mi">2022</span><span class="n">a</span><span class="o">-</span><span class="n">hda174b7_0</span>
<span class="w"> </span><span class="n">wheel</span><span class="w"> </span><span class="n">anaconda</span><span class="o">/</span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">noarch</span><span class="p">::</span><span class="n">wheel</span><span class="o">-</span><span class="mf">0.37</span><span class="o">.</span><span class="mi">1</span><span class="o">-</span><span class="n">pyhd3eb1b0_0</span>
<span class="w"> </span><span class="n">xz</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="n">arm64</span><span class="p">::</span><span class="n">xz</span><span class="o">-</span><span class="mf">5.2</span><span class="o">.</span><span class="mi">5</span><span class="o">-</span><span class="n">h1a28f6b_1</span>
<span class="w"> </span><span class="n">zlib</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="n">arm64</span><span class="p">::</span><span class="n">zlib</span><span class="o">-</span><span class="mf">1.2</span><span class="o">.</span><span class="mi">12</span><span class="o">-</span><span class="n">h5a0b063_2</span>
<span class="n">Proceed</span><span class="w"> </span><span class="p">([</span><span class="n">y</span><span class="p">]</span><span class="o">/</span><span class="n">n</span><span class="p">)</span><span class="err">?</span>
<span class="n">Downloading</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">Extracting</span><span class="w"> </span><span class="n">Packages</span>
<span class="n">python</span><span class="o">-</span><span class="mf">3.9</span><span class="o">.</span><span class="mi">11</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="mf">10.1</span><span class="w"> </span><span class="n">MB</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="c1">##################################################################################################################################### | 100%</span>
<span class="n">Preparing</span><span class="w"> </span><span class="n">transaction</span><span class="p">:</span><span class="w"> </span><span class="n">done</span>
<span class="n">Verifying</span><span class="w"> </span><span class="n">transaction</span><span class="p">:</span><span class="w"> </span><span class="n">done</span>
<span class="n">Executing</span><span class="w"> </span><span class="n">transaction</span><span class="p">:</span><span class="w"> </span><span class="n">done</span>
<span class="c1">#</span>
<span class="c1"># To activate this environment, use</span>
<span class="c1">#</span>
<span class="c1"># $ conda activate leo3911</span>
<span class="c1">#</span>
<span class="c1"># To deactivate an active environment, use</span>
<span class="c1">#</span>
<span class="c1"># $ conda deactivate</span>
</code></pre></div>
<p>检验安装成果:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>conda<span class="w"> </span>env<span class="w"> </span>list
<span class="c1"># conda environments:</span>
<span class="c1">#</span>
base<span class="w"> </span>*<span class="w"> </span>/opt/homebrew/Caskroom/miniconda/base
leo3811<span class="w"> </span>/opt/homebrew/Caskroom/miniconda/base/envs/leo3811
leo3911<span class="w"> </span>/opt/homebrew/Caskroom/miniconda/base/envs/leo3911
</code></pre></div>
<div class="highlight"><pre><span></span><code><span class="err">$</span><span class="w"> </span><span class="n">conda</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">PyQt</span>
<span class="n">Collecting</span><span class="w"> </span><span class="n">package</span><span class="w"> </span><span class="n">metadata</span><span class="w"> </span><span class="p">(</span><span class="n">current_repodata</span><span class="p">.</span><span class="n">json</span><span class="p">)</span><span class="err">:</span><span class="w"> </span><span class="n">done</span>
<span class="n">Solving</span><span class="w"> </span><span class="nl">environment</span><span class="p">:</span><span class="w"> </span><span class="n">done</span>
<span class="err">##</span><span class="w"> </span><span class="n">Package</span><span class="w"> </span><span class="k">Plan</span><span class="w"> </span><span class="err">##</span>
<span class="w"> </span><span class="n">environment</span><span class="w"> </span><span class="nl">location</span><span class="p">:</span><span class="w"> </span><span class="o">/</span><span class="n">opt</span><span class="o">/</span><span class="n">homebrew</span><span class="o">/</span><span class="n">Caskroom</span><span class="o">/</span><span class="n">miniconda</span><span class="o">/</span><span class="n">base</span><span class="o">/</span><span class="n">envs</span><span class="o">/</span><span class="n">leo3811</span>
<span class="w"> </span><span class="n">added</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">updated</span><span class="w"> </span><span class="nl">specs</span><span class="p">:</span>
<span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">pyqt</span>
<span class="n">The</span><span class="w"> </span><span class="n">following</span><span class="w"> </span><span class="k">NEW</span><span class="w"> </span><span class="n">packages</span><span class="w"> </span><span class="n">will</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="nl">INSTALLED</span><span class="p">:</span>
<span class="w"> </span><span class="n">adwaita</span><span class="o">-</span><span class="n">icon</span><span class="o">-</span><span class="n">theme</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">adwaita</span><span class="o">-</span><span class="n">icon</span><span class="o">-</span><span class="n">theme</span><span class="o">-</span><span class="mf">40.1.1</span><span class="o">-</span><span class="n">hca03da5_1</span>
<span class="w"> </span><span class="n">atk</span><span class="o">-</span><span class="mf">1.0</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">atk</span><span class="o">-</span><span class="mf">1.0</span><span class="o">-</span><span class="mf">2.36.0</span><span class="o">-</span><span class="n">h7fe96df_0</span>
<span class="w"> </span><span class="n">cairo</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">cairo</span><span class="o">-</span><span class="mf">1.16.0</span><span class="o">-</span><span class="n">h0ab239c_1</span>
<span class="w"> </span><span class="n">dbus</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">dbus</span><span class="o">-</span><span class="mf">1.13.18</span><span class="o">-</span><span class="n">h8280c03_0</span>
<span class="w"> </span><span class="n">epoxy</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">epoxy</span><span class="o">-</span><span class="mf">1.5.4</span><span class="o">-</span><span class="n">h1a28f6b_2</span>
<span class="w"> </span><span class="n">expat</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">expat</span><span class="o">-</span><span class="mf">2.4.4</span><span class="o">-</span><span class="n">hc377ac9_0</span>
<span class="w"> </span><span class="n">fontconfig</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">fontconfig</span><span class="o">-</span><span class="mf">2.13.1</span><span class="o">-</span><span class="n">h1f4a5ec_0</span>
<span class="w"> </span><span class="n">freetype</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">freetype</span><span class="o">-</span><span class="mf">2.11.0</span><span class="o">-</span><span class="n">h1192e45_0</span>
<span class="w"> </span><span class="n">fribidi</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">fribidi</span><span class="o">-</span><span class="mf">1.0.10</span><span class="o">-</span><span class="n">h1a28f6b_0</span>
<span class="w"> </span><span class="n">gdk</span><span class="o">-</span><span class="n">pixbuf</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">gdk</span><span class="o">-</span><span class="n">pixbuf</span><span class="o">-</span><span class="mf">2.42.6</span><span class="o">-</span><span class="n">h74ef11a_4</span>
<span class="w"> </span><span class="n">gettext</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">gettext</span><span class="o">-</span><span class="mf">0.21.0</span><span class="o">-</span><span class="n">h826f4ad_0</span>
<span class="w"> </span><span class="n">giflib</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">giflib</span><span class="o">-</span><span class="mf">5.2.1</span><span class="o">-</span><span class="n">h1a28f6b_0</span>
<span class="w"> </span><span class="n">glib</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">glib</span><span class="o">-</span><span class="mf">2.69.1</span><span class="o">-</span><span class="n">h98b2900_1</span>
<span class="w"> </span><span class="n">gobject</span><span class="o">-</span><span class="n">introspec</span><span class="o">~</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">gobject</span><span class="o">-</span><span class="n">introspection</span><span class="o">-</span><span class="mf">1.68.0</span><span class="o">-</span><span class="n">py38h3459c9f_3</span>
<span class="w"> </span><span class="n">graphite2</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">graphite2</span><span class="o">-</span><span class="mf">1.3.14</span><span class="o">-</span><span class="n">h0e5e14a_0</span>
<span class="w"> </span><span class="n">gtk3</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">gtk3</span><span class="o">-</span><span class="mf">3.24.21</span><span class="o">-</span><span class="n">h321fa23_1</span>
<span class="w"> </span><span class="n">harfbuzz</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">harfbuzz</span><span class="o">-</span><span class="mf">2.8.1</span><span class="o">-</span><span class="n">hffeda63_0</span>
<span class="w"> </span><span class="n">hicolor</span><span class="o">-</span><span class="n">icon</span><span class="o">-</span><span class="n">theme</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">hicolor</span><span class="o">-</span><span class="n">icon</span><span class="o">-</span><span class="n">theme</span><span class="o">-</span><span class="mf">0.17</span><span class="o">-</span><span class="n">hca03da5_2</span>
<span class="w"> </span><span class="n">icu</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">icu</span><span class="o">-</span><span class="mf">68.1</span><span class="o">-</span><span class="n">hc377ac9_0</span>
<span class="w"> </span><span class="n">jpeg</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">jpeg</span><span class="o">-</span><span class="mi">9</span><span class="n">e</span><span class="o">-</span><span class="n">h1a28f6b_0</span>
<span class="w"> </span><span class="n">krb5</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">krb5</span><span class="o">-</span><span class="mf">1.19.2</span><span class="o">-</span><span class="n">h3b8d789_0</span>
<span class="w"> </span><span class="n">libedit</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">libedit</span><span class="o">-</span><span class="mf">3.1.20210910</span><span class="o">-</span><span class="n">h1a28f6b_0</span>
<span class="w"> </span><span class="n">libevent</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">libevent</span><span class="o">-</span><span class="mf">2.1.12</span><span class="o">-</span><span class="n">hf27765b_0</span>
<span class="w"> </span><span class="n">libiconv</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">libiconv</span><span class="o">-</span><span class="mf">1.16</span><span class="o">-</span><span class="n">h1a28f6b_2</span>
<span class="w"> </span><span class="n">libpng</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">libpng</span><span class="o">-</span><span class="mf">1.6.37</span><span class="o">-</span><span class="n">hb8d0fd4_0</span>
<span class="w"> </span><span class="n">libpq</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">libpq</span><span class="o">-</span><span class="mf">12.9</span><span class="o">-</span><span class="n">h65cfe13_1</span>
<span class="w"> </span><span class="n">librsvg</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">librsvg</span><span class="o">-</span><span class="mf">2.50.7</span><span class="o">-</span><span class="n">h90a7944_0</span>
<span class="w"> </span><span class="n">libtiff</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">libtiff</span><span class="o">-</span><span class="mf">4.2.0</span><span class="o">-</span><span class="n">h01837e1_1</span>
<span class="w"> </span><span class="n">libwebp</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">libwebp</span><span class="o">-</span><span class="mf">1.2.2</span><span class="o">-</span><span class="n">h68602c7_0</span>
<span class="w"> </span><span class="n">libwebp</span><span class="o">-</span><span class="n">base</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">libwebp</span><span class="o">-</span><span class="n">base</span><span class="o">-</span><span class="mf">1.2.2</span><span class="o">-</span><span class="n">h1a28f6b_0</span>
<span class="w"> </span><span class="n">libxml2</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">libxml2</span><span class="o">-</span><span class="mf">2.9.14</span><span class="o">-</span><span class="n">h8c5e841_0</span>
<span class="w"> </span><span class="n">libxslt</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">libxslt</span><span class="o">-</span><span class="mf">1.1.34</span><span class="o">-</span><span class="n">h9833966_0</span>
<span class="w"> </span><span class="n">llvm</span><span class="o">-</span><span class="n">openmp</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">llvm</span><span class="o">-</span><span class="n">openmp</span><span class="o">-</span><span class="mf">12.0.0</span><span class="o">-</span><span class="n">haf9daa7_1</span>
<span class="w"> </span><span class="n">lz4</span><span class="o">-</span><span class="n">c</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">lz4</span><span class="o">-</span><span class="n">c</span><span class="o">-</span><span class="mf">1.9.3</span><span class="o">-</span><span class="n">hc377ac9_0</span>
<span class="w"> </span><span class="n">ninja</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">ninja</span><span class="o">-</span><span class="mf">1.10.2</span><span class="o">-</span><span class="n">hca03da5_5</span>
<span class="w"> </span><span class="n">ninja</span><span class="o">-</span><span class="n">base</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">ninja</span><span class="o">-</span><span class="n">base</span><span class="o">-</span><span class="mf">1.10.2</span><span class="o">-</span><span class="n">h525c30c_5</span>
<span class="w"> </span><span class="n">nspr</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">nspr</span><span class="o">-</span><span class="mf">4.33</span><span class="o">-</span><span class="n">hc377ac9_0</span>
<span class="w"> </span><span class="n">nss</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">nss</span><span class="o">-</span><span class="mf">3.74</span><span class="o">-</span><span class="n">h142855e_0</span>
<span class="w"> </span><span class="n">pango</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">pango</span><span class="o">-</span><span class="mf">1.48.7</span><span class="o">-</span><span class="n">h79d33a7_0</span>
<span class="w"> </span><span class="n">pcre</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">pcre</span><span class="o">-</span><span class="mf">8.45</span><span class="o">-</span><span class="n">hc377ac9_0</span>
<span class="w"> </span><span class="n">pixman</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">pixman</span><span class="o">-</span><span class="mf">0.40.0</span><span class="o">-</span><span class="n">h1a28f6b_0</span>
<span class="w"> </span><span class="n">pyqt</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">pyqt</span><span class="o">-</span><span class="mf">5.15.2</span><span class="o">-</span><span class="n">py38he8f2410_0</span>
<span class="w"> </span><span class="n">qt</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">qt</span><span class="o">-</span><span class="mf">5.15.2</span><span class="o">-</span><span class="n">h4e944ae_2</span>
<span class="w"> </span><span class="n">zstd</span><span class="w"> </span><span class="n">pkgs</span><span class="o">/</span><span class="n">main</span><span class="o">/</span><span class="n">osx</span><span class="o">-</span><span class="nl">arm64</span><span class="p">:</span><span class="err">:</span><span class="n">zstd</span><span class="o">-</span><span class="mf">1.5.2</span><span class="o">-</span><span class="n">h8574219_0</span>
<span class="n">Proceed</span><span class="w"> </span><span class="p">(</span><span class="o">[</span><span class="n">y</span><span class="o">]/</span><span class="n">n</span><span class="p">)</span><span class="vm">?</span>
</code></pre></div>
<blockquote>
<p>$ pip install leo</p>
</blockquote>
<p><img alt="PyQtWebEngine" src="https://ipic.zoomquiet.top/2022-05-29-zshot%202022-05-29%2021.41.02.jpg"/></p>
<p>也有安装失败, 持续自动降级现象...</p>
<p>最终成功安装了:</p>
<ul>
<li>Successfully built lazy-object-proxy wrapt tornado</li>
<li>Installing collected packages: zipp, wrapt, typing-extensions, traitlets, pytz, pyrsistent, MarkupSafe, lazy-object-proxy, dialite, attrs, webruntime, tornado, tomli, sphinxcontrib-serializinghtml, sphinxcontrib-qthelp, sphinxcontrib-jsmath, sphinxcontrib-htmlhelp, sphinxcontrib-devhelp, sphinxcontrib-applehelp, snowballstemmer, pscript, platformdirs, mccabe, jupyter-core, jsonschema, Jinja2, isort, importlib-metadata, imagesize, fastjsonschema, docutils, dill, babel, astroid, alabaster, sphinx, six, pylint, pyflakes, nbformat, future, flexx, leo</li>
<li>Successfully installed Jinja2-3.1.2 MarkupSafe-2.1.1 alabaster-0.7.12 astroid-2.11.5 attrs-21.4.0 babel-2.10.1 dialite-0.5.3 dill-0.3.5.1 docutils-0.17.1 fastjsonschema-2.15.3 flexx-0.8.4 future-0.18.2 imagesize-1.3.0 importlib-metadata-4.11.4 isort-5.10.1 jsonschema-4.5.1 jupyter-core-4.10.0 lazy-object-proxy-1.7.1 leo-5.9 mccabe-0.7.0 nbformat-5.4.0 platformdirs-2.5.2 pscript-0.7.7 pyflakes-2.4.0 pylint-2.13.9 pyrsistent-0.18.1 pytz-2022.1 six-1.16.0 snowballstemmer-2.2.0 sphinx-4.5.0 sphinxcontrib-applehelp-1.0.2 sphinxcontrib-devhelp-1.0.2 sphinxcontrib-htmlhelp-2.0.0 sphinxcontrib-jsmath-1.0.1 sphinxcontrib-qthelp-1.0.3 sphinxcontrib-serializinghtml-1.1.5 tomli-2.0.1 tornado-6.1 traitlets-5.2.1.post0 typing-extensions-4.2.0 webruntime-0.5.8 wrapt-1.14.1 zipp-3.8.0</li>
</ul>
<p>但是, 运行时报出神奇错误:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>leo
Sorry,<span class="w"> </span><span class="s2">"python"</span><span class="w"> </span>cannot<span class="w"> </span>be<span class="w"> </span>run<span class="w"> </span>on<span class="w"> </span>this<span class="w"> </span>version<span class="w"> </span>of<span class="w"> </span>macOS.<span class="w"> </span>Qt<span class="w"> </span>requires<span class="w"> </span>macOS<span class="w"> </span><span class="m">11</span>.1.0<span class="w"> </span>or<span class="w"> </span>later,<span class="w"> </span>you<span class="w"> </span>have<span class="w"> </span>macOS<span class="w"> </span><span class="m">10</span>.16.0.
</code></pre></div>
<h3 id="_1">混合安装:<a class="headerlink" href="#_1" title="Permanent link">¶</a></h3>
<blockquote>
<p>果断 M1 环境中当前还是 brew 体系最靠谱</p>
</blockquote>
<p>参考: <a href="https://www.zhihu.com/question/437075754/answer/1993415429">MacBook Pro m1版本怎么安装python 的pyqt5? - 知乎</a></p>
<ul>
<li>先用 <code>abrew install pyqt@5</code> 完成针对 ARM 环境的 Qt 安装</li>
<li>然后将对应安装好的 lib 手工复制到对应 conda 环境中<ul>
<li>比如, 重新创建专用环境</li>
<li><code>conda create -n leo3912 python=3.9.12</code></li>
</ul>
</li>
<li>则, 手工复制的是:<ul>
<li><code>/opt/homebrew/Cellar/pyqt@5/5.15.6/lib/python3.9/site-packages/</code> 中所有目录</li>
<li>到 <code>/opt/homebrew/Caskroom/miniconda/base/envs/leo3912/lib/python3.9/site-packages/</code></li>
</ul>
</li>
</ul>
<p>包含:</p>
<div class="highlight"><pre><span></span><code>PyQt3D-5.15.5.dist-info
PyQt5
PyQt5-5.15.6.dist-info
PyQt5_sip-12.9.0-py3.9.egg-info
PyQtChart-5.15.5.dist-info
PyQtDataVisualization-5.15.5.dist-info
PyQtNetworkAuth-5.15.5.dist-info
PyQtPurchasing-5.15.5.dist-info
</code></pre></div>
<p>从官方 <a href="https://github.com/leo-editor/leo-editor/releases/latest">Latest</a> 链接中下载最新原代码包, 部署到 <code>/opt/bin</code></p>
<p>然后, 在对应环境中调用:</p>
<div class="highlight"><pre><span></span><code><span class="p">(</span><span class="n">conda</span><span class="p">:</span><span class="w"> </span><span class="n">leo3912</span><span class="p">)</span>
<span class="o">$</span><span class="w"> </span><span class="n">python</span><span class="w"> </span><span class="o">/</span><span class="n">opt</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">leo</span><span class="o">/</span><span class="n">launchLeo</span><span class="o">.</span><span class="n">py</span>
<span class="n">setting</span><span class="w"> </span><span class="n">leoID</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="n">os</span><span class="o">.</span><span class="n">getenv</span><span class="p">(</span><span class="s1">'USER'</span><span class="p">):</span><span class="w"> </span><span class="s1">'zoomq'</span>
<span class="n">PYLINTHOME</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="s1">'/Users/zoomq/Library/Caches/pylint'</span><span class="w"> </span><span class="n">but</span><span class="w"> </span><span class="n">obsolescent</span><span class="w"> </span><span class="s1">'/Users/zoomq/.pylint.d'</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">found</span><span class="p">;</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">safely</span><span class="w"> </span><span class="n">remove</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">latter</span>
<span class="n">duplicate</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="ow">not</span><span class="w"> </span><span class="n">conflicting</span><span class="p">)</span><span class="w"> </span><span class="n">key</span><span class="w"> </span><span class="n">bindings</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">myLeoSettings</span><span class="o">.</span><span class="n">leo</span>
<span class="n">all</span><span class="w"> </span><span class="n">Alt</span><span class="o">+</span><span class="p">)</span><span class="w"> </span><span class="n">move</span><span class="o">-</span><span class="n">past</span><span class="o">-</span><span class="n">close</span>
<span class="n">all</span><span class="w"> </span><span class="n">Alt</span><span class="o">+</span><span class="p">)</span><span class="w"> </span><span class="n">move</span><span class="o">-</span><span class="n">past</span><span class="o">-</span><span class="n">close</span>
<span class="n">duplicate</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="ow">not</span><span class="w"> </span><span class="n">conflicting</span><span class="p">)</span><span class="w"> </span><span class="n">key</span><span class="w"> </span><span class="n">bindings</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">myLeoSettings</span><span class="o">.</span><span class="n">leo</span>
<span class="n">all</span><span class="w"> </span><span class="n">Alt</span><span class="o">+</span><span class="p">}</span><span class="w"> </span><span class="n">forward</span><span class="o">-</span><span class="n">paragraph</span>
<span class="n">all</span><span class="w"> </span><span class="n">Alt</span><span class="o">+</span><span class="p">}</span><span class="w"> </span><span class="n">forward</span><span class="o">-</span><span class="n">paragraph</span><span class="o">-</span><span class="n">extend</span><span class="o">-</span><span class="n">selection</span>
<span class="n">duplicate</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="ow">not</span><span class="w"> </span><span class="n">conflicting</span><span class="p">)</span><span class="w"> </span><span class="n">key</span><span class="w"> </span><span class="n">bindings</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">myLeoSettings</span><span class="o">.</span><span class="n">leo</span>
<span class="n">all</span><span class="w"> </span><span class="n">Ctrl</span><span class="o">+</span><span class="p">(</span><span class="w"> </span><span class="n">add</span><span class="o">-</span><span class="n">comments</span>
<span class="n">all</span><span class="w"> </span><span class="n">Ctrl</span><span class="o">+</span><span class="p">(</span><span class="w"> </span><span class="n">add</span><span class="o">-</span><span class="n">comments</span>
<span class="n">duplicate</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="ow">not</span><span class="w"> </span><span class="n">conflicting</span><span class="p">)</span><span class="w"> </span><span class="n">key</span><span class="w"> </span><span class="n">bindings</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">myLeoSettings</span><span class="o">.</span><span class="n">leo</span>
<span class="n">all</span><span class="w"> </span><span class="n">Ctrl</span><span class="o">+</span><span class="p">)</span><span class="w"> </span><span class="n">delete</span><span class="o">-</span><span class="n">comments</span>
<span class="n">all</span><span class="w"> </span><span class="n">Ctrl</span><span class="o">+</span><span class="p">)</span><span class="w"> </span><span class="n">delete</span><span class="o">-</span><span class="n">comments</span>
<span class="n">all</span><span class="w"> </span><span class="n">Ctrl</span><span class="o">+</span><span class="p">)</span><span class="w"> </span><span class="n">delete</span><span class="o">-</span><span class="n">comments</span>
<span class="n">duplicate</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="ow">not</span><span class="w"> </span><span class="n">conflicting</span><span class="p">)</span><span class="w"> </span><span class="n">key</span><span class="w"> </span><span class="n">bindings</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">myLeoSettings</span><span class="o">.</span><span class="n">leo</span>
<span class="n">all</span><span class="w"> </span><span class="n">Ctrl</span><span class="o">+</span><span class="p">{</span><span class="w"> </span><span class="n">promote</span>
<span class="n">all</span><span class="w"> </span><span class="n">Ctrl</span><span class="o">+</span><span class="p">{</span><span class="w"> </span><span class="n">promote</span>
<span class="n">duplicate</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="ow">not</span><span class="w"> </span><span class="n">conflicting</span><span class="p">)</span><span class="w"> </span><span class="n">key</span><span class="w"> </span><span class="n">bindings</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">myLeoSettings</span><span class="o">.</span><span class="n">leo</span>
<span class="n">all</span><span class="w"> </span><span class="n">Ctrl</span><span class="o">+</span><span class="p">}</span><span class="w"> </span><span class="n">demote</span>
<span class="n">all</span><span class="w"> </span><span class="n">Ctrl</span><span class="o">+</span><span class="p">}</span><span class="w"> </span><span class="n">demote</span>
<span class="n">Leo</span><span class="w"> </span><span class="mf">6.6</span><span class="o">.</span><span class="mi">2</span>
<span class="n">Python</span><span class="w"> </span><span class="mf">3.9</span><span class="o">.</span><span class="mi">12</span><span class="p">,</span><span class="w"> </span><span class="n">PyQt</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="mf">5.15</span><span class="o">.</span><span class="mi">3</span>
<span class="n">darwin</span>
<span class="n">expand_css_constants</span><span class="w"> </span><span class="n">Unresolved</span><span class="w"> </span><span class="err">@</span><span class="n">constants</span>
<span class="p">[</span>
<span class="w"> </span><span class="s1">'@bookmarks_base_decoration'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@bookmarks_children_family'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@bookmarks_base_border'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@bookmarks_base_family'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@checkbox-font-family'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@dialog-font-family'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@dialog-font-weight'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@status-font-family'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@dialog-font-style'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@dialog-font-size'</span>
<span class="p">]</span>
<span class="n">qt</span><span class="o">.</span><span class="n">qpa</span><span class="o">.</span><span class="n">fonts</span><span class="p">:</span><span class="w"> </span><span class="n">Populating</span><span class="w"> </span><span class="n">font</span><span class="w"> </span><span class="n">family</span><span class="w"> </span><span class="n">aliases</span><span class="w"> </span><span class="n">took</span><span class="w"> </span><span class="mi">163</span><span class="w"> </span><span class="n">ms</span><span class="o">.</span><span class="w"> </span><span class="n">Replace</span><span class="w"> </span><span class="n">uses</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">missing</span><span class="w"> </span><span class="n">font</span><span class="w"> </span><span class="n">family</span><span class="w"> </span><span class="s2">"Monoid Retina"</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">one</span><span class="w"> </span><span class="n">that</span><span class="w"> </span><span class="n">exists</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">avoid</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="n">cost</span><span class="o">.</span>
<span class="ow">not</span><span class="w"> </span><span class="n">found</span><span class="p">:</span><span class="w"> </span><span class="s1">'@auto 4py3ch.md'</span>
<span class="ow">not</span><span class="w"> </span><span class="n">found</span><span class="p">:</span><span class="w"> </span><span class="s1">'@auto 4py4ch.md'</span>
<span class="ow">not</span><span class="w"> </span><span class="n">found</span><span class="p">:</span><span class="w"> </span><span class="s1">'@auto 4py5ch.md'</span>
<span class="ow">not</span><span class="w"> </span><span class="n">found</span><span class="p">:</span><span class="w"> </span><span class="s1">'@auto 4py6ch.md'</span>
<span class="ow">not</span><span class="w"> </span><span class="n">found</span><span class="p">:</span><span class="w"> </span><span class="s1">'@auto 4pyend.md'</span>
<span class="ow">not</span><span class="w"> </span><span class="n">found</span><span class="p">:</span><span class="w"> </span><span class="o">/</span><span class="n">Users</span><span class="o">/</span><span class="n">zoomq</span><span class="o">/</span><span class="n">Sites</span><span class="o">/</span><span class="mf">101.</span><span class="n">camp</span><span class="o">/</span><span class="n">utility</span><span class="o">/</span><span class="n">announcer</span><span class="o">/</span><span class="n">tasks</span><span class="o">.</span><span class="n">py</span>
<span class="ow">not</span><span class="w"> </span><span class="n">found</span><span class="p">:</span><span class="w"> </span><span class="o">/</span><span class="n">Users</span><span class="o">/</span><span class="n">zoomq</span><span class="o">/</span><span class="n">Sites</span><span class="o">/</span><span class="mf">101.</span><span class="n">camp</span><span class="o">/</span><span class="n">utility</span><span class="o">/</span><span class="n">pol</span><span class="o">/</span><span class="n">camp</span><span class="o">.</span><span class="n">yaml</span>
<span class="ow">not</span><span class="w"> </span><span class="n">found</span><span class="p">:</span><span class="w"> </span><span class="o">/</span><span class="n">Users</span><span class="o">/</span><span class="n">zoomq</span><span class="o">/</span><span class="n">Sites</span><span class="o">/</span><span class="mf">101.</span><span class="n">camp</span><span class="o">/</span><span class="n">utility</span><span class="o">/</span><span class="n">pol</span><span class="o">/</span><span class="n">st</span><span class="o">.</span><span class="n">py</span>
<span class="ow">not</span><span class="w"> </span><span class="n">found</span><span class="p">:</span><span class="w"> </span><span class="o">/</span><span class="n">Users</span><span class="o">/</span><span class="n">zoomq</span><span class="o">/</span><span class="n">Sites</span><span class="o">/</span><span class="mf">101.</span><span class="n">camp</span><span class="o">/</span><span class="n">utility</span><span class="o">/</span><span class="n">pol</span><span class="o">/</span><span class="n">tasks</span><span class="o">.</span><span class="n">py</span>
<span class="ow">not</span><span class="w"> </span><span class="n">found</span><span class="p">:</span><span class="w"> </span><span class="o">/</span><span class="n">Users</span><span class="o">/</span><span class="n">zoomq</span><span class="o">/</span><span class="n">Sites</span><span class="o">/</span><span class="mf">101.</span><span class="n">camp</span><span class="o">/</span><span class="n">utility</span><span class="o">/</span><span class="nb">pow</span><span class="o">/</span><span class="n">tasks</span><span class="o">.</span><span class="n">py</span>
<span class="ow">not</span><span class="w"> </span><span class="n">found</span><span class="p">:</span><span class="w"> </span><span class="o">/</span><span class="n">Users</span><span class="o">/</span><span class="n">zoomq</span><span class="o">/</span><span class="n">Sites</span><span class="o">/</span><span class="mf">101.</span><span class="n">camp</span><span class="o">/</span><span class="n">_course</span><span class="o">/</span><span class="mi">101</span><span class="n">camp1py</span><span class="o">/</span><span class="nb">pow</span><span class="o">/</span><span class="n">tasks</span><span class="o">.</span><span class="n">py</span>
<span class="n">expand_css_constants</span><span class="w"> </span><span class="n">Unresolved</span><span class="w"> </span><span class="err">@</span><span class="n">constants</span>
<span class="p">[</span>
<span class="w"> </span><span class="s1">'@bookmarks_base_decoration'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@bookmarks_children_family'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@bookmarks_base_border'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@bookmarks_base_family'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@checkbox-font-family'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@dialog-font-family'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@dialog-font-weight'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@status-font-family'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@dialog-font-style'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@dialog-font-size'</span>
<span class="p">]</span>
<span class="n">expand_css_constants</span><span class="w"> </span><span class="n">Unresolved</span><span class="w"> </span><span class="err">@</span><span class="n">constants</span>
<span class="p">[</span>
<span class="w"> </span><span class="s1">'@bookmarks_base_decoration'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@bookmarks_children_family'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@bookmarks_base_border'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@bookmarks_base_family'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@checkbox-font-family'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@dialog-font-family'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@dialog-font-weight'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@status-font-family'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@dialog-font-style'</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'@dialog-font-size'</span>
<span class="p">]</span>
<span class="n">wrote</span><span class="w"> </span><span class="o">/</span><span class="n">Users</span><span class="o">/</span><span class="n">zoomq</span><span class="o">/.</span><span class="n">leo</span><span class="o">/</span><span class="n">leo</span><span class="o">.</span><span class="n">session</span>
<span class="n">wrote</span><span class="w"> </span><span class="n">recent</span><span class="w"> </span><span class="n">file</span><span class="p">:</span><span class="w"> </span><span class="o">/</span><span class="n">Users</span><span class="o">/</span><span class="n">zoomq</span><span class="o">/.</span><span class="n">leo</span><span class="o">/.</span><span class="n">leoRecentFiles</span><span class="o">.</span><span class="n">txt</span>
</code></pre></div>
<p><img alt="Leo 6.6.2" src="https://ipic.zoomquiet.top/2022-05-29-zshot%202022-05-29%2022.10.10-1.jpg"/></p>
<p>可以正常启动后, 将指令包装为一个别名:</p>
<p><code>~/.bash_profile</code> 中追加:</p>
<div class="highlight"><pre><span></span><code>alias leo6lanch="python /opt/bin/leo/launchLeo.py >> /dev/null 2>&1 &"
</code></pre></div>
<p>日常在终端中就两步调用:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>conda<span class="w"> </span>activate<span class="w"> </span>leo3912
$<span class="w"> </span>leo6lanch
</code></pre></div>
<h4 id="ps">PS:<a class="headerlink" href="#ps" title="Permanent link">¶</a></h4>
<p>如果以上安装 leo 后, 直接在 conda 环境中运行, 将发现:</p>
<div class="highlight"><pre><span></span><code><span class="o">$</span><span class="w"> </span><span class="n">leo</span>
<span class="n">Traceback</span><span class="w"> </span><span class="p">(</span><span class="n">most</span><span class="w"> </span><span class="n">recent</span><span class="w"> </span><span class="n">call</span><span class="w"> </span><span class="n">last</span><span class="p">):</span>
<span class="w"> </span><span class="n">File</span><span class="w"> </span><span class="s2">"/opt/homebrew/Caskroom/miniconda/base/envs/leo3912/bin/leo"</span><span class="p">,</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="mi">8</span><span class="p">,</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="w"> </span><span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="n">run</span><span class="p">())</span>
<span class="w"> </span><span class="n">File</span><span class="w"> </span><span class="s2">"/opt/homebrew/Caskroom/miniconda/base/envs/leo3912/lib/python3.9/site-packages/leo/core/runLeo.py"</span><span class="p">,</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="mi">72</span><span class="p">,</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">run</span>
<span class="w"> </span><span class="n">g</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">loadManager</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">fileName</span><span class="p">,</span><span class="w"> </span><span class="n">pymacs</span><span class="p">)</span>
<span class="w"> </span><span class="n">File</span><span class="w"> </span><span class="s2">"/opt/homebrew/Caskroom/miniconda/base/envs/leo3912/lib/python3.9/site-packages/leo/core/leoApp.py"</span><span class="p">,</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="mi">2252</span><span class="p">,</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="nb">load</span>
<span class="w"> </span><span class="n">t1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">time</span><span class="o">.</span><span class="n">clock</span><span class="p">()</span>
<span class="n">AttributeError</span><span class="p">:</span><span class="w"> </span><span class="n">module</span><span class="w"> </span><span class="s1">'time'</span><span class="w"> </span><span class="n">has</span><span class="w"> </span><span class="n">no</span><span class="w"> </span><span class="n">attribute</span><span class="w"> </span><span class="s1">'clock'</span>
</code></pre></div>
<p>经过代码探查发现, <code>time.clock()</code> 已经在 Py3.8 之后废弃,
也就是说, Leo 最新版本中一定不包含这种函式,
即, pip 安装过程中为了兼容, 自动降级到某个老版本中了...
经过探查:</p>
<p>/opt/homebrew/Caskroom/miniconda/base/envs/leo3912/lib/python3.9/site-packages/leo/core/leoVersion.py</p>
<p>果断写着 <code>5.9-b2</code> , 是19年的版本;</p>
<h2 id="summary">Summary<a class="headerlink" href="#summary" title="Permanent link">¶</a></h2>
<blockquote>
<p>小结</p>
</blockquote>
<p>看起来复杂, 其实只是探查了各种可能性后, 才知道如何可以合理的在 M1 芯片的 macOS 环境中安装 Leo:</p>
<ul>
<li>基于 arm 版本 homebrew 安装 <code>PyQt@5</code></li>
<li>基于 miniconda 的 Py3.9 环境安装其它依赖</li>
<li>基于 官方源代码中的 <code>launchLeo.py</code> 来启动</li>
</ul>
<p>具体关键指令:</p>
<ul>
<li>abrew install PyQt@5</li>
<li>abrew install miniconda<ul>
<li>注意, 正式使用前, 要运行: <code>conda init bash</code></li>
<li>参考: <a href="https://docs.conda.io/projects/conda/en/latest/dev-guide/deep-dive-activation.html">Deep dive: conda init and activate — conda 4.13.0.post1+0adcd595 documentation</a></li>
</ul>
</li>
</ul>
<p>应该可以在 <code>~/.bash_profile</code> 中找到以下类似配置:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># >>> conda initialize >>></span>
<span class="c1"># !! Contents within this block are managed by 'conda init' !!</span>
<span class="n">__conda_setup</span><span class="o">=</span><span class="s2">"$('/opt/homebrew/Caskroom/miniconda/base/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"</span>
<span class="k">if</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="o">$</span><span class="err">?</span><span class="w"> </span><span class="o">-</span><span class="n">eq</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">];</span><span class="w"> </span><span class="n">then</span>
<span class="w"> </span><span class="n">eval</span><span class="w"> </span><span class="s2">"$__conda_setup"</span>
<span class="k">else</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="o">-</span><span class="n">f</span><span class="w"> </span><span class="s2">"/opt/homebrew/Caskroom/miniconda/base/etc/profile.d/conda.sh"</span><span class="w"> </span><span class="p">];</span><span class="w"> </span><span class="n">then</span>
<span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="s2">"/opt/homebrew/Caskroom/miniconda/base/etc/profile.d/conda.sh"</span>
<span class="w"> </span><span class="k">else</span>
<span class="w"> </span><span class="k">export</span><span class="w"> </span><span class="n">PATH</span><span class="o">=</span><span class="s2">"/opt/homebrew/Caskroom/miniconda/base/bin:$PATH"</span>
<span class="w"> </span><span class="n">fi</span>
<span class="n">fi</span>
<span class="n">unset</span><span class="w"> </span><span class="n">__conda_setup</span>
<span class="c1"># <<< conda initialize <<<</span>
</code></pre></div>
<ul>
<li>用 conda info 检验当前环境是否正常</li>
<li>然后, 创建 Leo 专用环境:<ul>
<li>conda create -n leo3912 python=3.9.12</li>
<li>注意, 当前 brew 环境中默认安装的是 <code>python@3.9</code> 环境, 所以, 对应 conda 环境也应该是 3.9 以上的</li>
</ul>
</li>
<li>手工将 PyQt 包从 brew 环境中复制到 conda 对应环境中, 例如:<ul>
<li><code>/opt/homebrew/Cellar/pyqt@5/5.15.6/lib/python3.9/site-packages/</code> 中所有目录</li>
<li>到 <code>/opt/homebrew/Caskroom/miniconda/base/envs/leo3912/lib/python3.9/site-packages/</code></li>
</ul>
</li>
<li>手工从 github 中下载部署最新 Leo 源代码</li>
<li>然后, 从 conda 环境中调用 <code>launchLeo.py</code> 即可</li>
<li>可以正常启动后, 将指令包装为一个别名:</li>
</ul>
<p><code>~/.bash_profile</code> 中追加:</p>
<div class="highlight"><pre><span></span><code>alias leo6lanch="python /opt/bin/leo/launchLeo.py >> /dev/null 2>&1 &"
</code></pre></div>
<p>日常在终端中就两步调用:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>conda<span class="w"> </span>activate<span class="w"> </span>leo3912
$<span class="w"> </span>leo6lanch
</code></pre></div>
<h2 id="logging">logging<a class="headerlink" href="#logging" title="Permanent link">¶</a></h2>
<ul>
<li>220529 整理为文章</li>
<li>220528 miniconda 成功</li>
<li>220527 决定重来</li>
<li>220506 再尝试, 未果</li>
<li>220401 尝试, 未果</li>
<li>211113 触发, 存疑</li>
</ul>如何安定进入 M1maxMBP2021-11-14T22:42:00+08:002021-11-15T09:59:31+08:00Zoom.Quiettag:blog.zoomquiet.io,2021-11-14:/211114M1max-re-inti-MBP.html
<h2 id="background">background<a class="headerlink" href="#background" title="Permanent link">¶</a></h2>
<p>13年入的 MBP 坑,
当时 17吋 顶配, 在 MACAO 实体店拿的;
16年初突然不可用,
(后来检查才发现, 是长期使用功率不匹配的电源才反复导致主板出问题)
急忙去 …</p>
<h2 id="background">background<a class="headerlink" href="#background" title="Permanent link">¶</a></h2>
<p>13年入的 MBP 坑,
当时 17吋 顶配, 在 MACAO 实体店拿的;
16年初突然不可用,
(后来检查才发现, 是长期使用功率不匹配的电源才反复导致主板出问题)
急忙去 MACAO 新授权店拿了 13吋高配(i7,4核,16G内存,512G硬盘);
因为是主力开发/日常用机,
就没敢一直升级系统, 10.X 系列一直用下来;</p>
<p>到今年下半年, 明显撑不住了:</p>
<ul>
<li>OBS 录制 720P 以上视频, 撑不住10分钟就崩溃</li>
<li>腾讯会议本地录制, 30分钟的内容要转换20分钟</li>
<li>ffmpeg 进行视频处理, 几乎都是 0.42 倍率在进行</li>
<li>docker 容器一启动就要等待3分钟</li>
<li>...</li>
</ul>
<p>如此种种已经开始干挠日常工作/学习/创作/...</p>
<p>怎么办?
磕金/升级呗...</p>
<blockquote>
<p>忍了一年...</p>
</blockquote>
<p>去年 M1 芯片 Air 一出来就想买的,
但是, 大家都说 M1 还不成熟, 各种软件都要等待兼容...</p>
<p>就忍着, 一直到10月, 一下子有了 M1pre/max,
性能又翻倍了,
立即入手: 14吋, M1max 10核, 64G 内存, 1T 硬盘;</p>
<p>等了快三周, 终于到手, 如何开始安定迁入?</p>
<h2 id="goal">goal<a class="headerlink" href="#goal" title="Permanent link">¶</a></h2>
<blockquote>
<p>最短, 最平滑, 进入, 折腾最少</p>
</blockquote>
<p>日常依赖其实并不多主要就几块儿:</p>
<ul>
<li>终端相关:<ul>
<li>iTerm2 为界面</li>
<li>bash v4.4.12 配合 bash_it 定制日常环境</li>
<li>PyENV 管理多种 Python 运行时<ul>
<li>conda 管理 Leo 安装运行时</li>
</ul>
</li>
<li>RVM 管理多种 Ruby 运行时</li>
<li>NVM 管理多种 Node 运行时</li>
<li>ASDF 管理多种 Elixir 运行时</li>
<li>...以及各种 AliYun/Heroku/AWS/...依赖CLI 管理工具</li>
<li>特别是 HomeBrew, 管理了超过200种 UNIX 实用工具</li>
</ul>
</li>
<li>浏览器相关:<ul>
<li>WaterFox 安装使用传统 Firefox 插件, 以便查阅积累超过15年, <strong>30+万</strong>网页的本地资源库 ~ 基于 Scrapbook 收集管理, 但是 Firefox 56.0 版本之后不再支持原有插件体系, 只能迁移到 <code>水狐</code> 继续</li>
<li>Vivaldi 进行日常工作管理, 因为内置 <code>树状标签管理</code> 又兼容 Chrome 扩展而且没有 Google 广告</li>
<li>Brave 进行日常探索学习, 也兼容 Chrome 扩展</li>
<li>Edge 进行日常资源管理, 比如团队仓库/公众号/云资源/...兼容部分 Chrome 扩展</li>
<li>Chrome 进行日常 Google 系工具使用, 核心就是 gmail</li>
<li>Chromium 进行日常系统测试, 专门用以走查 web 系统功能</li>
<li>以上浏览器都需要关键拓展来确保日常最基础可用:<ul>
<li>SwitchyOmega ~ 快速代理切换工具, 以便使用不同网络来访问有关资源</li>
<li>The Great Suspender Original ~ 自动将不活跃标签内存回收</li>
<li>Create Link ~ 快速形成 Markdown 格式网地址文本</li>
<li>Choosy ~ 快速将网址丢入其它浏览器/应用中加载</li>
<li>...</li>
</ul>
</li>
<li>...以及部分终端中无头浏览器辅助进行爬虫开发</li>
</ul>
</li>
<li>开发相关:<ul>
<li>XCode ~ 获得基本编译支持</li>
<li>Sublime Text 3 ~ 获得快速编辑支持</li>
<li>VScode ~ 获得综合开发支持</li>
<li>DBeaver ~ 获得数据库管理界面</li>
<li>Docker+VirtualBox ~ 虚拟主机支持</li>
<li>...以及其它42+以上开发支持工具</li>
</ul>
</li>
<li>媒体相关:<ul>
<li>IINA+VLC 看视频</li>
<li>GIMP+Inkscape 进行图片处理</li>
<li>screenflow 进行视频编辑</li>
<li>...以及其它42+以上媒体处理工具</li>
</ul>
</li>
<li>系统相关:<ul>
<li>muCommander ~ 日常双窗口资源管理, 通过快捷键提高文件管理效率, JAVA 实现可运行在所有系统中, 当年从 WindowsNT 平台开始就习惯了有关操作</li>
<li>Display Menu ~ 快速调节不同显示器分辨率</li>
<li>Lunar+Flux ~ 快速调节所有显示器亮度/对比度/...</li>
<li>aText ~ 快速管理自定义常用短语</li>
<li>iPic ~ 快速上传图片到图床, 获得 markdown 格式图片引用文本</li>
<li>Spectacle ~ 窗口布局快捷键支持工具, 可以高效安排多窗口排列</li>
<li>Bartender ~ 从2就开始付费使用, 现在已经到 v4, 可以将 menu bar 中应用图标管理, 折叠到子菜单中...</li>
<li>Caffeine ~ 便捷激活 mac 系统不休眠</li>
<li>...以及其它42+以上系统增强工具</li>
</ul>
</li>
<li>办公相关:<ul>
<li>iWork ~ mac 味儿 Office</li>
<li>OpenOffice ~ linux 味儿 Office</li>
<li>WPS ~ 国产味儿 office</li>
<li>XMind+Freemind ~ 思维导图支持</li>
<li>yED+PlantUML ~ 流程图/架构图/... UML 味图谱支持</li>
<li>Axure+蓝湖 ~ 产品设计支持</li>
<li>微信/企业微信/QQ/Lark/zoom.us/Slack/... ~ 工作协同用工具栈</li>
<li>...以及其它42+以上团队协作支持工具</li>
</ul>
</li>
</ul>
<p>以及所有涉及正版软件的许可证升级/配置/采购/...</p>
<p>还有以往形成各种工程簇, 在本地不同目录入口中, 形成的对应快速<code>软链接</code> ...</p>
<h2 id="quickly">quickly<a class="headerlink" href="#quickly" title="Permanent link">¶</a></h2>
<p>以上所有, 都人工进行重新配置的话, 目测至少得一个月, 才能陆续到位,
毕竟是以往多年尝试/配置/选择的成果;</p>
<p>如何简洁完成呢?</p>
<p>(周5收到, 周1 就应该全面完成迁移, 以便投入日常工作)</p>
<p>快速尝试了几个姿势:</p>
<ul>
<li>人工配置, 光是安装 iTemer2 进行基本配置:<ul>
<li>字体</li>
<li>颜色</li>
<li>...etc, 就用了一小时</li>
<li>那么多常用工具逐一配置到可用, 绝对无法简单完成</li>
</ul>
</li>
<li>Time Machine ~ 常规推荐操作:<ul>
<li>以往专门配置了个 1T SSD 移动硬盘来进行备份</li>
<li>先用 4小时, 完成最新一次备份, 涉及40G 数据的更新</li>
<li>然后, 使用 <code>迁移助理</code> ~ 死活无法发现这个非法 <code>时间机器</code> ?</li>
<li>也可能, 用 10.X 系统备份的数据, 无法识别为 12.X 系统兼容时间备份</li>
</ul>
</li>
<li>rsync ~ 之前从 Windows -> Linux -> MAC 的异种系统迁移过程中立过大功<ul>
<li>用1小时, 将所有工作数据备份到另外移动硬盘中</li>
<li>再开始尝试同步时, 想到这只能完成数据迁移, 最耗时的应用配置并没有涉及...</li>
</ul>
</li>
<li>冷静一下, 搜索官方文档, 才发现:<ul>
<li><a href="https://support.apple.com/zh-cn/HT204350">将内容迁移到一台新的 Mac 上 - Apple 支持 (中国)</a></li>
<li><code>迁移助理</code> 这一实用工具有三种迁移姿势:<ul>
<li>从另一台 Mac 或是 Time Machine 备份中转送数据</li>
<li>从一个 Window 机器获得数据</li>
<li>发送数据到另一台 Mac</li>
</ul>
</li>
<li>老rMBP 保有所有正常使用环境和应用, 新 M1MBP 是目标机</li>
<li>都打开 <code>迁移助理</code> <ul>
<li>老rMBP 选择 <code>To another Mac</code></li>
<li>新 M1MBP 选择 <code>From a Mac</code></li>
<li>并明确对传送的帐号如何处理, 俺选择-><strong>创建新帐号</strong></li>
<li>然后点 <code>继续</code> 完成安全配对后, 即开始 <code>点对点</code> 传输</li>
<li>当然, 要先确保在同一个网络中</li>
</ul>
</li>
<li>看起来可行, 开始: </li>
</ul>
</li>
</ul>
<p><img alt="p2p" src="https://ipic.zoomquiet.top/2021-11-15-ScreenShot2021-11-15%2009.55.38.jpg"/></p>
<p>嗯嗯嗯...嘦10小时等一晩上就好,</p>
<p><img alt="80万文件" src="https://ipic.zoomquiet.top/2021-11-14-ScreenShot2021-11-14%2023.32.28.jpg"/></p>
<p>果然:</p>
<p>༄ sudo du -hs *</p>
<div class="highlight"><pre><span></span><code><span class="mf">111</span><span class="n">M</span><span class="w"> </span><span class="n">Shared</span>
<span class="mf">265</span><span class="n">G</span><span class="w"> </span><span class="n">zoomq</span>
<span class="mf">4.2</span><span class="n">G</span><span class="w"> </span><span class="n">zoomquiet</span>
</code></pre></div>
<p>༄ who i am</p>
<div class="highlight"><pre><span></span><code>zoomq ttys004 2021-11-14 18:58
</code></pre></div>
<p>手工尝试时, 创建用户是 <code>zoomquiet</code> 仅仅完成 iCloud 主要数据同步,
而 <code>zoomq</code> 是从 linux 时代, 使用超过 15 年的帐号,</p>
<p>经过一夜自动转送, 合理同步了超过 450G 数据:</p>
<p><img alt="450+G" src="https://ipic.zoomquiet.top/2021-11-14-ScreenShot2021-11-14%2023.37.06.jpg"/></p>
<p>进入系统后发现, 基本所有习惯操作都可用, 只有少数几个要对应配置:</p>
<ul>
<li>关键的 WaterFox 无法打开 Scrapbook 收集的本地网页, 以及控制界面<ul>
<li>搜索后, 尝试安装对应 <code>Waterfox Classic 2021.10</code> 版本</li>
<li>替代原先使用的 <code>Waterfox Classic 2019.12</code></li>
<li>只是, 专门为 M1 芯片开发的 <code>Waterfox.G4.0.2.1.ARM</code> 却也已经放弃了 FireFox 经典 XUL 扩展体系, 无法安装 Scrapbook 插件</li>
</ul>
</li>
<li>Python 经常崩溃, 搜索后, 手工重建有关 openssl 两个核心模块的链接即可修复</li>
<li>HomeBrew 要对应升级, 发现有大量失败, 要求先升级 XCode<ul>
<li>正常升级</li>
<li>并:<ul>
<li>$ sudo xcode-select --install</li>
<li>$ sudo xcodebuild -license accept </li>
</ul>
</li>
<li>再来, 也就都流畅完成了</li>
</ul>
</li>
</ul>
<p><img alt="12G" src="https://ipic.zoomquiet.top/2021-11-14-ScreenShot2021-11-15%2000.11.27.jpg"/></p>
<p>甚至于, 原先在 老 rMBP 每次安装要编译半小时的 ffmpeg 也无缝自动完成升级:</p>
<p><img alt="10核 ffmpeg" src="https://ipic.zoomquiet.top/2021-11-14-ScreenShot2021-11-14%2020.53.00.jpg"/></p>
<p>这一下子就有 <code>10核降重任</code> 感觉了 ;-)</p>
<h2 id="murmur">murmur<a class="headerlink" href="#murmur" title="Permanent link">¶</a></h2>
<blockquote>
<p>记要关键增补指令过程...</p>
<p>homebrew</p>
</blockquote>
<p><code>$ brew update</code></p>
<div class="highlight"><pre><span></span><code>...
Error:
homebrew-core is a shallow clone.
homebrew-cask is a shallow clone.
To `brew update`, first run:
git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow
git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask fetch --unshallow
</code></pre></div>
<blockquote>
<p>These commands may take a few minutes to run due to the large size of the repositories.
This restriction has been made on GitHub's request because updating shallow
clones is an extremely expensive operation due to the tree layout and traffic of
Homebrew/homebrew-core and Homebrew/homebrew-cask. We don't do this for you
automatically to avoid repeatedly performing an expensive unshallow operation in
CI systems (which should instead be fixed to not use shallow clones). Sorry for
the inconvenience!</p>
<p>༄ git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow</p>
</blockquote>
<div class="highlight"><pre><span></span><code><span class="n">remote</span><span class="o">:</span><span class="w"> </span><span class="n">Enumerating</span><span class="w"> </span><span class="n">objects</span><span class="o">:</span><span class="w"> </span><span class="mi">346864</span><span class="o">,</span><span class="w"> </span><span class="n">done</span><span class="o">.</span>
<span class="n">remote</span><span class="o">:</span><span class="w"> </span><span class="n">Counting</span><span class="w"> </span><span class="n">objects</span><span class="o">:</span><span class="w"> </span><span class="mi">100</span><span class="o">%</span><span class="w"> </span><span class="o">(</span><span class="mi">346859</span><span class="o">/</span><span class="mi">346859</span><span class="o">),</span><span class="w"> </span><span class="n">done</span><span class="o">.</span>
<span class="n">remote</span><span class="o">:</span><span class="w"> </span><span class="n">Compressing</span><span class="w"> </span><span class="n">objects</span><span class="o">:</span><span class="w"> </span><span class="mi">100</span><span class="o">%</span><span class="w"> </span><span class="o">(</span><span class="mi">151509</span><span class="o">/</span><span class="mi">151509</span><span class="o">),</span><span class="w"> </span><span class="n">done</span><span class="o">.</span>
<span class="n">remote</span><span class="o">:</span><span class="w"> </span><span class="n">Total</span><span class="w"> </span><span class="mi">338208</span><span class="w"> </span><span class="o">(</span><span class="n">delta</span><span class="w"> </span><span class="mi">196986</span><span class="o">),</span><span class="w"> </span><span class="n">reused</span><span class="w"> </span><span class="mi">324905</span><span class="w"> </span><span class="o">(</span><span class="n">delta</span><span class="w"> </span><span class="mi">183898</span><span class="o">),</span><span class="w"> </span><span class="n">pack</span><span class="o">-</span><span class="n">reused</span><span class="w"> </span><span class="mi">0</span>
<span class="err">接收对象中</span><span class="o">:</span><span class="w"> </span><span class="mi">100</span><span class="o">%</span><span class="w"> </span><span class="o">(</span><span class="mi">338208</span><span class="sr">/338208), 93.70 MiB | 5.90 MiB/s</span><span class="o">,</span><span class="w"> </span><span class="err">完成</span><span class="o">.</span>
<span class="err">处理</span><span class="w"> </span><span class="n">delta</span><span class="w"> </span><span class="err">中</span><span class="o">:</span><span class="w"> </span><span class="mi">100</span><span class="o">%</span><span class="w"> </span><span class="o">(</span><span class="mi">196986</span><span class="o">/</span><span class="mi">196986</span><span class="o">),</span><span class="w"> </span><span class="err">完成</span><span class="w"> </span><span class="mi">7813</span><span class="w"> </span><span class="err">个本地对象</span><span class="o">.</span>
<span class="err">来自</span><span class="w"> </span><span class="n">github</span><span class="o">.</span><span class="na">com</span><span class="o">:</span><span class="n">Homebrew</span><span class="o">/</span><span class="n">homebrew</span><span class="o">-</span><span class="n">core</span>
<span class="w"> </span><span class="n">ef5c358418d</span><span class="o">..</span><span class="mi">5</span><span class="n">c8ec008df4</span><span class="w"> </span><span class="n">master</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="n">origin</span><span class="o">/</span><span class="n">master</span>
</code></pre></div>
<blockquote>
<p>༄ git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask fetch --unshallow</p>
</blockquote>
<div class="highlight"><pre><span></span><code><span class="n">remote</span><span class="o">:</span><span class="w"> </span><span class="n">Enumerating</span><span class="w"> </span><span class="n">objects</span><span class="o">:</span><span class="w"> </span><span class="mi">28649</span><span class="o">,</span><span class="w"> </span><span class="n">done</span><span class="o">.</span>
<span class="n">remote</span><span class="o">:</span><span class="w"> </span><span class="n">Counting</span><span class="w"> </span><span class="n">objects</span><span class="o">:</span><span class="w"> </span><span class="mi">100</span><span class="o">%</span><span class="w"> </span><span class="o">(</span><span class="mi">25990</span><span class="o">/</span><span class="mi">25990</span><span class="o">),</span><span class="w"> </span><span class="n">done</span><span class="o">.</span>
<span class="n">remote</span><span class="o">:</span><span class="w"> </span><span class="n">Compressing</span><span class="w"> </span><span class="n">objects</span><span class="o">:</span><span class="w"> </span><span class="mi">100</span><span class="o">%</span><span class="w"> </span><span class="o">(</span><span class="mi">8663</span><span class="o">/</span><span class="mi">8663</span><span class="o">),</span><span class="w"> </span><span class="n">done</span><span class="o">.</span>
<span class="n">remote</span><span class="o">:</span><span class="w"> </span><span class="n">Total</span><span class="w"> </span><span class="mi">20358</span><span class="w"> </span><span class="o">(</span><span class="n">delta</span><span class="w"> </span><span class="mi">14980</span><span class="o">),</span><span class="w"> </span><span class="n">reused</span><span class="w"> </span><span class="mi">17036</span><span class="w"> </span><span class="o">(</span><span class="n">delta</span><span class="w"> </span><span class="mi">11692</span><span class="o">),</span><span class="w"> </span><span class="n">pack</span><span class="o">-</span><span class="n">reused</span><span class="w"> </span><span class="mi">0</span>
<span class="err">接收对象中</span><span class="o">:</span><span class="w"> </span><span class="mi">100</span><span class="o">%</span><span class="w"> </span><span class="o">(</span><span class="mi">20358</span><span class="sr">/20358), 6.42 MiB | 6.31 MiB/s</span><span class="o">,</span><span class="w"> </span><span class="err">完成</span><span class="o">.</span>
<span class="err">处理</span><span class="w"> </span><span class="n">delta</span><span class="w"> </span><span class="err">中</span><span class="o">:</span><span class="w"> </span><span class="mi">100</span><span class="o">%</span><span class="w"> </span><span class="o">(</span><span class="mi">14980</span><span class="o">/</span><span class="mi">14980</span><span class="o">),</span><span class="w"> </span><span class="err">完成</span><span class="w"> </span><span class="mi">1655</span><span class="w"> </span><span class="err">个本地对象</span><span class="o">.</span>
<span class="err">来自</span><span class="w"> </span><span class="n">github</span><span class="o">.</span><span class="na">com</span><span class="o">:</span><span class="n">Homebrew</span><span class="o">/</span><span class="n">homebrew</span><span class="o">-</span><span class="n">cask</span>
<span class="w"> </span><span class="mi">6</span><span class="n">faccf1ee4</span><span class="o">..</span><span class="mi">134</span><span class="n">f0d09b2</span><span class="w"> </span><span class="n">master</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="n">origin</span><span class="o">/</span><span class="n">master</span>
</code></pre></div>
<p>根据 <code>brew doctor</code> 诊断建议, 进行依赖安装时:</p>
<blockquote>
<p>༄ brew install aom assimp bdw-gc brotli c-ares dav1d dbus double-conversion frei0r giflib guile jemalloc leptonica libarchive libb2 libbluray libev libproxy libpthread-stubs libsamplerate libsndfile libsodium libsoxr libvidstab libx11 libxau libxcb libxdmcp libxext libxrender luajit-openresty lz4 mpdecimal mujs nghttp2 opencore-amr openjdk openjdk@8 openjpeg opusfile pybind11 rav1e rubberband speex srt tesseract uchardet vapoursynth xorgproto zeromq zimg zstd</p>
</blockquote>
<p>有大量报错:</p>
<p>...</p>
<div class="highlight"><pre><span></span><code><span class="nl">Error</span><span class="p">:</span><span class="w"> </span><span class="n">python</span><span class="mf">@3.9</span><span class="o">:</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">bottle</span><span class="w"> </span><span class="n">needs</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">Apple</span><span class="w"> </span><span class="n">Command</span><span class="w"> </span><span class="n">Line</span><span class="w"> </span><span class="n">Tools</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">installed</span><span class="p">.</span>
<span class="w"> </span><span class="n">You</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">them</span><span class="p">,</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">desired</span><span class="p">,</span><span class="w"> </span><span class="n">with</span><span class="o">:</span>
<span class="w"> </span><span class="n">xcode</span><span class="o">-</span><span class="n">select</span><span class="w"> </span><span class="o">--</span><span class="n">install</span>
<span class="n">You</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">try</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="n">source</span><span class="w"> </span><span class="n">with</span><span class="o">:</span>
<span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="o">--</span><span class="n">build</span><span class="o">-</span><span class="n">from</span><span class="o">-</span><span class="n">source</span><span class="w"> </span><span class="n">python</span><span class="mf">@3.9</span>
<span class="n">Please</span><span class="w"> </span><span class="n">note</span><span class="w"> </span><span class="n">building</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="n">source</span><span class="w"> </span><span class="n">is</span><span class="w"> </span><span class="n">unsupported</span><span class="p">.</span><span class="w"> </span><span class="n">You</span><span class="w"> </span><span class="n">will</span><span class="w"> </span><span class="n">encounter</span><span class="w"> </span><span class="n">build</span>
<span class="n">failures</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">some</span><span class="w"> </span><span class="n">formulae</span><span class="p">.</span><span class="w"> </span><span class="n">If</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">experience</span><span class="w"> </span><span class="n">any</span><span class="w"> </span><span class="n">issues</span><span class="w"> </span><span class="n">please</span><span class="w"> </span><span class="n">create</span><span class="w"> </span><span class="n">pull</span>
<span class="n">requests</span><span class="w"> </span><span class="n">instead</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">asking</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">help</span><span class="w"> </span><span class="n">on</span><span class="w"> </span><span class="n">Homebrew</span><span class="err">'</span><span class="n">s</span><span class="w"> </span><span class="n">GitHub</span><span class="p">,</span><span class="w"> </span><span class="n">Twitter</span><span class="w"> </span><span class="n">or</span><span class="w"> </span><span class="n">any</span><span class="w"> </span><span class="n">other</span>
<span class="n">official</span><span class="w"> </span><span class="n">channels</span><span class="p">.</span>
<span class="p">...</span>
<span class="nl">Error</span><span class="p">:</span><span class="w"> </span><span class="n">gcc</span><span class="o">:</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">bottle</span><span class="w"> </span><span class="n">needs</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">Apple</span><span class="w"> </span><span class="n">Command</span><span class="w"> </span><span class="n">Line</span><span class="w"> </span><span class="n">Tools</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">installed</span><span class="p">.</span>
<span class="w"> </span><span class="n">You</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">them</span><span class="p">,</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">desired</span><span class="p">,</span><span class="w"> </span><span class="n">with</span><span class="o">:</span>
<span class="w"> </span><span class="n">xcode</span><span class="o">-</span><span class="n">select</span><span class="w"> </span><span class="o">--</span><span class="n">install</span>
<span class="n">You</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">try</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="n">source</span><span class="w"> </span><span class="n">with</span><span class="o">:</span>
<span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="o">--</span><span class="n">build</span><span class="o">-</span><span class="n">from</span><span class="o">-</span><span class="n">source</span><span class="w"> </span><span class="n">gcc</span>
<span class="n">Please</span><span class="w"> </span><span class="n">note</span><span class="w"> </span><span class="n">building</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="n">source</span><span class="w"> </span><span class="n">is</span><span class="w"> </span><span class="n">unsupported</span><span class="p">.</span><span class="w"> </span><span class="n">You</span><span class="w"> </span><span class="n">will</span><span class="w"> </span><span class="n">encounter</span><span class="w"> </span><span class="n">build</span>
<span class="n">failures</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">some</span><span class="w"> </span><span class="n">formulae</span><span class="p">.</span><span class="w"> </span><span class="n">If</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">experience</span><span class="w"> </span><span class="n">any</span><span class="w"> </span><span class="n">issues</span><span class="w"> </span><span class="n">please</span><span class="w"> </span><span class="n">create</span><span class="w"> </span><span class="n">pull</span>
<span class="n">requests</span><span class="w"> </span><span class="n">instead</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">asking</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">help</span><span class="w"> </span><span class="n">on</span><span class="w"> </span><span class="n">Homebrew</span><span class="err">'</span><span class="n">s</span><span class="w"> </span><span class="n">GitHub</span><span class="p">,</span><span class="w"> </span><span class="n">Twitter</span><span class="w"> </span><span class="n">or</span><span class="w"> </span><span class="n">any</span><span class="w"> </span><span class="n">other</span>
<span class="n">official</span><span class="w"> </span><span class="n">channels</span><span class="p">.</span>
<span class="nl">Error</span><span class="p">:</span><span class="w"> </span><span class="n">gcc</span><span class="o">:</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">bottle</span><span class="w"> </span><span class="n">needs</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">Apple</span><span class="w"> </span><span class="n">Command</span><span class="w"> </span><span class="n">Line</span><span class="w"> </span><span class="n">Tools</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">installed</span><span class="p">.</span>
<span class="w"> </span><span class="n">You</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">them</span><span class="p">,</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">desired</span><span class="p">,</span><span class="w"> </span><span class="n">with</span><span class="o">:</span>
<span class="w"> </span><span class="n">xcode</span><span class="o">-</span><span class="n">select</span><span class="w"> </span><span class="o">--</span><span class="n">install</span>
<span class="n">You</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">try</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="n">source</span><span class="w"> </span><span class="n">with</span><span class="o">:</span>
<span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="o">--</span><span class="n">build</span><span class="o">-</span><span class="n">from</span><span class="o">-</span><span class="n">source</span><span class="w"> </span><span class="n">gcc</span>
<span class="n">Please</span><span class="w"> </span><span class="n">note</span><span class="w"> </span><span class="n">building</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="n">source</span><span class="w"> </span><span class="n">is</span><span class="w"> </span><span class="n">unsupported</span><span class="p">.</span><span class="w"> </span><span class="n">You</span><span class="w"> </span><span class="n">will</span><span class="w"> </span><span class="n">encounter</span><span class="w"> </span><span class="n">build</span>
<span class="n">failures</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">some</span><span class="w"> </span><span class="n">formulae</span><span class="p">.</span><span class="w"> </span><span class="n">If</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">experience</span><span class="w"> </span><span class="n">any</span><span class="w"> </span><span class="n">issues</span><span class="w"> </span><span class="n">please</span><span class="w"> </span><span class="n">create</span><span class="w"> </span><span class="n">pull</span>
<span class="n">requests</span><span class="w"> </span><span class="n">instead</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">asking</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">help</span><span class="w"> </span><span class="n">on</span><span class="w"> </span><span class="n">Homebrew</span><span class="err">'</span><span class="n">s</span><span class="w"> </span><span class="n">GitHub</span><span class="p">,</span><span class="w"> </span><span class="n">Twitter</span><span class="w"> </span><span class="n">or</span><span class="w"> </span><span class="n">any</span><span class="w"> </span><span class="n">other</span>
<span class="n">official</span><span class="w"> </span><span class="n">channels</span><span class="p">.</span>
</code></pre></div>
<p>完成 XCode 升级后再来, 就一切顺利了 ;-)</p>
<p>以及推荐:</p>
<p><a href="https://github.com/exelban/stats">exelban/stats: macOS system monitor in your menu bar</a></p>
<p>免费监察一堆传感器数值:
<img alt="stats" src="https://ipic.zoomquiet.top/2021-11-14-ScreenShot2021-11-14%2022.51.27.jpg"/></p>
<h2 id="timekeeping">timekeeping<a class="headerlink" href="#timekeeping" title="Permanent link">¶</a></h2>
<ul>
<li>1.0h 尝试手工恢复</li>
<li>1.0h 尝试 timemechine 恢复</li>
<li>0.5h 探索其它可能</li>
<li>1.0h 尝试 迁移助手</li>
<li>8.0h 点对点 传输 450+G 数据+应用</li>
<li>1.0h 尝试恢复 WaterFox 职能</li>
<li>1.5h 尝试恢复关键工具许可证</li>
<li>1.0h 尝试解决 Python 问题</li>
<li>1.5h 记要/发布</li>
<li>...</li>
</ul>
<p><img alt="终于基本可用" src="https://ipic.zoomquiet.top/2021-11-14-ScreenShot2021-11-14%2023.31.28.jpg"/></p>
<h2 id="refer">refer.<a class="headerlink" href="#refer" title="Permanent link">¶</a></h2>
<ul>
<li><a href="https://docs.python.org/3/using/mac.html">5. Using Python on a Mac — Python 3.10.0 documentation</a><ul>
<li><a href="https://developer.apple.com/forums/thread/119429">My application crashed with invali… | Apple Developer Forums</a></li>
<li><a href="https://gist.github.com/llbbl/c54f44d028d014514d5d837f64e60bac">fix missing openssl files in catalina</a></li>
<li><a href="https://stackoverflow.com/questions/59888499/macos-catalina-python-quit-unexpectedly-error">macOS Catalina: Python Quit unexpectedly error - Stack Overflow</a></li>
<li>...</li>
</ul>
</li>
</ul>
<h1 id="logging">logging<a class="headerlink" href="#logging" title="Permanent link">¶</a></h1>
<ul>
<li>211114 找到办法, 快速完成迁移</li>
<li>211113 init.</li>
</ul>VNC回归轻松2020-07-04T19:42:00+08:002020-07-25T10:43:30+08:00ZoomQuiettag:blog.zoomquiet.io,2020-07-04:/200704-easy-vnc.html<p>SCM/ 跨平台桌面控制最纯粹和轻松的协议桟还是原生的好...</p>
<h2 id="bg">BG.<a class="headerlink" href="#bg" title="Permanent link">¶</a></h2>
<p>很早就有这种需求:</p>
<p>比如当年参与开发浏览器时,
对应工程是 windows only 的,
而俺的笔记本是 macOS,
所以, 必须有个方便的远程控制工具,将 PB 上的桌面变成本地一个窗口,
并能无缝进行切换控制.</p>
<p>当年用 vnc server 的 windows 版本.</p>
<p>后来创业时, 要确保客户端同时可以安定运行在 win7 以及 linux 上,
更加需要一个通用的全平台桌面控制工具.</p>
<p>当时用的是 TeamViewer :</p>
<ul>
<li>商业软件</li>
<li>非常稳定</li>
<li>功能良好</li>
</ul>
<p>问题是, 对于私人商用非常敏感,
用的时间长点儿, 就判定为非法商用直接断掉了.</p>
<h2 id="problems">problems<a class="headerlink" href="#problems" title="Permanent link">¶</a></h2>
<p>然后, 也尝试过各种其它通用类 VNC 工具:</p>
<ul>
<li>X2Go 安装失败</li>
<li>TigerVNC/UltraVNC/RDP/... 不兼容</li>
<li>NoMachine NX ~ 唉嘛开始还好, 真正一用各种 diss, 而且无法删除</li>
<li>还有国产的什么太阳花桌面 ~ 根本无用</li>
</ul>
<p>只能切换到 RealVNC, 也是商用, 但是, 印象不错;</p>
<ul>
<li>好容易按照官方文档在 mac/ubuntu 间配置好</li>
<li>也用了一段时间</li>
<li>没想到, 一次系统升级后无论怎么折腾<ul>
<li>远程进入后都是黑屏</li>
<li>无法进入 GNOME 桌面.</li>
</ul>
</li>
</ul>
<h2 id="asking">asking<a class="headerlink" href="#asking" title="Permanent link">¶</a></h2>
<blockquote>
<p>搜索才发现, 这是常见问题...</p>
</blockquote>
<p>尝试了一堆方法都没办法解决, 那个糟心哪...</p>
<p>想想, 用 RealVNC 其实和 TeamViewer 没什么区别:</p>
<ul>
<li>每次连接主机, 都要先去人家官网绕一圈</li>
<li>注册一台主机, 而且免费有限额,只能5台</li>
<li>真正连接自己本地局域网旁边一台机器时</li>
<li>其实, 无论客户端/服务端 都要连接官网检验是否合法</li>
<li>而且, 在使用过程中, 俺的所有操作也一定有对应监察数据上报..</li>
</ul>
<p>也就是说, 俺用俺自己的主机, 就得向厂商老实汇报思想, 否则断你没商量.</p>
<p>俺为什么要这么贱?</p>
<h2 id="fixed">fixed<a class="headerlink" href="#fixed" title="Permanent link">¶</a></h2>
<blockquote>
<p>回归 FLOSS 社区内置方案吧...</p>
</blockquote>
<p>安装标准 vnc 服务:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>sudo<span class="w"> </span>apt<span class="w"> </span>install<span class="w"> </span>vnc4server<span class="w"> </span>xfce4<span class="w"> </span>xfce4-goodies
</code></pre></div>
<p>配置访问口令:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>vncpasswd
</code></pre></div>
<p>指定启动桌面 ~/.vnc/xstartup :</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="ch">#!/bin/bash</span>
startxfce4<span class="w"> </span><span class="p">&</span>
</code></pre></div></td></tr></table></div>
<p>并启用配置:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>chmod<span class="w"> </span>+x<span class="w"> </span>~/.vnc/xstartup
</code></pre></div>
<p>启动服务:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>vnc4server
</code></pre></div>
<p>检验状态:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>ss<span class="w"> </span>-ltn
...
LISTEN<span class="w"> </span><span class="m">0</span><span class="w"> </span><span class="m">5</span><span class="w"> </span>*:5901<span class="w"> </span>*:*
</code></pre></div>
<blockquote>
<p>注意: 如果有防火墙的话, 要打开 5901 的访问</p>
</blockquote>
<p>macOS 本地代理端口:</p>
<div class="highlight"><pre><span></span><code>༄ ssh -L 5901:127.0.0.1:5901 -C -N -l <主机用户> <主机IP>
</code></pre></div>
<p>(也就是将 Linux 主机上的 :5901 用 SSH 工具映射为本地 :5901)</p>
<p><img alt="连接" src="http://ydlj.zoomquiet.top/ipic/2020-07-25-ScreenShot%202020-07-25%2010.37.01.jpg"/></p>
<p>使用本地端口:</p>
<div class="highlight"><pre><span></span><code>vnc://localhost:5901
</code></pre></div>
<p><strong>Bazinga</strong></p>
<p><img alt="win7vbox" src="http://ydlj.zoomquiet.top/ipic/2020-07-25-ScreenShot%202020-07-25%2010.39.36.jpg"/></p>
<ul>
<li>Ubuntu 中安装 vncserver 以及 xfce4 桌面</li>
<li>Ubuntu 中启动 vncserver</li>
<li>macOS 中用 SSH 反向代理对应端口</li>
<li>用 macOS 内置远程桌面工具直连进入 Ubuntu 桌面<ul>
<li>安装 VirtualBOX </li>
<li>加载 win7 镜像</li>
<li>同时自由使用 windiws 环境以及 linux 工具</li>
</ul>
</li>
</ul>
<p>而且速度比之前各种 VNC 工具要快, 充分发挥了本地网络能力.</p>
<h2 id="refer">refer.<a class="headerlink" href="#refer" title="Permanent link">¶</a></h2>
<ul>
<li><a href="https://linuxconfig.org/vnc-server-on-ubuntu-18-04-bionic-beaver-linux">VNC server on Ubuntu 18.04 Bionic Beaver Linux - LinuxConfig.org</a></li>
<li><a href="https://cat.pdx.edu/platforms/mac/remote-access/vnc-to-linux/">VNC from Mac to Linux – Computer Action Team</a></li>
<li><a href="https://www.linode.com/docs/applications/remote-desktop/install-vnc-on-ubuntu-18-04/">Install VNC on Ubuntu 18.04 | Linode</a></li>
<li><a href="https://www.linode.com/community/questions/18877/how-do-i-set-up-vnc-with-mac-osx">How do I set up VNC with Mac OSX? | Linode Questions</a></li>
<li><a href="https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-vnc-on-ubuntu-14-04">How to Install and Configure VNC on Ubuntu 14.04 | DigitalOcean</a></li>
<li>...</li>
</ul>
<h2 id="logging">logging<a class="headerlink" href="#logging" title="Permanent link">¶</a></h2>
<ul>
<li>200725 zoomquiet pub</li>
<li>200704 zoomquiet 解决</li>
<li>200626 zoomquiet init.</li>
</ul>Elixir 中列出 Map 中值键对的折腾...2020-01-08T00:00:00+08:002020-01-09T12:37:57+08:00Zoom.Quiettag:blog.zoomquiet.io,2020-01-08:/200108-ex-map-enum.html
<p>因为各种原因吧...</p>
<ul>
<li>很早在 ECUG 就接触了 Erlang<ul>
<li>但是, 怪异的语法,以及狭小的应用领域,一直没真正使用起来</li>
<li>现在, 发现 Elixir 很好的解 …</li></ul></li></ul>
<p>因为各种原因吧...</p>
<ul>
<li>很早在 ECUG 就接触了 Erlang<ul>
<li>但是, 怪异的语法,以及狭小的应用领域,一直没真正使用起来</li>
<li>现在, 发现 Elixir 很好的解决了 OTP 生态的通用应用问题</li>
</ul>
</li>
<li>所以, 开始折腾...</li>
<li>结果, 撞见各种值得嗯哼的事儿...</li>
</ul>
<h2 id="env">env.<a class="headerlink" href="#env" title="Permanent link">¶</a></h2>
<p>༄ screenfetch</p>
<div class="highlight"><pre><span></span><code> <span class="s s-Atom">-/+:.</span> <span class="s s-Atom">zoomq@</span><span class="nv">ZQ160626rMBP</span>
<span class="o">:</span><span class="s s-Atom">++++.</span> <span class="nv">OS</span><span class="o">:</span> <span class="mi">64</span><span class="s s-Atom">bit</span> <span class="nv">Mac</span> <span class="nv">OS</span> <span class="nv">X</span> <span class="mf">10.12.6</span> <span class="mi">16</span><span class="nv">G2136</span>
<span class="s s-Atom">/+++/.</span> <span class="nv">Kernel</span><span class="o">:</span> <span class="s s-Atom">x86_64</span> <span class="nv">Darwin</span> <span class="mf">16.7.0</span>
<span class="p">.</span><span class="o">:-::-</span> <span class="p">.</span><span class="s s-Atom">+/:-</span><span class="err">``</span><span class="p">.</span><span class="o">::-</span> <span class="nv">Uptime</span><span class="o">:</span> <span class="mi">30</span><span class="s s-Atom">d</span> <span class="mi">12</span><span class="s s-Atom">h</span> <span class="mi">38</span><span class="s s-Atom">m</span>
<span class="p">.</span><span class="o">:</span><span class="s s-Atom">/++++++/::::/++++++/:</span><span class="err">`</span> <span class="nv">Packages</span><span class="o">:</span> <span class="mi">241</span>
<span class="p">.</span><span class="o">:</span><span class="s s-Atom">///////////////////////:</span><span class="err">`</span> <span class="nv">Shell</span><span class="o">:</span> <span class="s s-Atom">bash</span>
<span class="s s-Atom">////////////////////////</span><span class="err">`</span> <span class="nv">Resolution</span><span class="o">:</span> <span class="mi">2560</span><span class="s s-Atom">x1440</span>
<span class="s s-Atom">-+++++++++++++++++++++++</span><span class="err">`</span> <span class="nv">DE</span><span class="o">:</span> <span class="nv">Aqua</span>
<span class="s s-Atom">/++++++++++++++++++++++/</span> <span class="nv">WM</span><span class="o">:</span> <span class="nv">Quartz</span> <span class="nv">Compositor</span>
<span class="o">/</span><span class="s s-Atom">sssssssssssssssssssssss</span><span class="p">.</span> <span class="nv">WM</span> <span class="nv">Theme</span><span class="o">:</span> <span class="nv">Blue</span>
<span class="o">:</span><span class="s s-Atom">ssssssssssssssssssssssss</span><span class="o">-</span> <span class="nv">CPU</span><span class="o">:</span> <span class="nv">Intel</span> <span class="nv">Core</span> <span class="s s-Atom">i7</span><span class="o">-</span><span class="mi">5557</span><span class="nv">U</span> <span class="s s-Atom">@</span> <span class="mf">3.10</span><span class="nv">GHz</span>
<span class="s s-Atom">osssssssssssssssssssssssso/</span><span class="err">`</span> <span class="nv">GPU</span><span class="o">:</span> <span class="nv">Intel</span> <span class="nv">Iris</span> <span class="nv">Graphics</span> <span class="mi">6100</span>
<span class="err">`</span><span class="s s-Atom">syyyyyyyyyyyyyyyyyyyyyyyy+</span><span class="err">`</span> <span class="nv">RAM</span><span class="o">:</span> <span class="mi">9318</span><span class="nv">MiB</span> <span class="o">/</span> <span class="mi">16384</span><span class="nv">MiB</span>
<span class="err">`</span><span class="s s-Atom">ossssssssssssssssssssss</span><span class="o">/</span>
<span class="o">:</span><span class="s s-Atom">ooooooooooooooooooo+.</span>
<span class="err">`</span><span class="o">:+</span><span class="s s-Atom">oo+/:-..-:/+o+/-</span>
</code></pre></div>
<ul>
<li>Erlang/OTP 21 [erts-10.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]</li>
<li>Elixir 1.9.1 (compiled with Erlang/OTP 20)</li>
</ul>
<h2 id="problem">problem<a class="headerlink" href="#problem" title="Permanent link">¶</a></h2>
<blockquote>
<p>使用 Plug 快速开发 Slack 插件...</p>
</blockquote>
<p>首先得完成基于 Plug 的 API 服务,
这其中最关键的是从 GET/POST 协议请求中获得 Slack 转发过来的用户指令;</p>
<p>官方文档中 demo 形似:</p>
<div class="highlight"><pre><span></span><code><span class="n">defmodule</span><span class="w"> </span><span class="n">Example</span><span class="p">.</span><span class="n">Plug</span><span class="p">.</span><span class="n">VerifyRequest</span><span class="w"> </span><span class="n">do</span>
<span class="w"> </span><span class="n">defmodule</span><span class="w"> </span><span class="n">IncompleteRequestError</span><span class="w"> </span><span class="n">do</span>
<span class="w"> </span><span class="nv">@moduledoc</span><span class="w"> </span><span class="ss">"""</span>
<span class="ss"> Error raised when a required field is missing.</span>
<span class="ss"> """</span>
<span class="w"> </span><span class="n">defexception</span><span class="w"> </span><span class="nl">message</span><span class="p">:</span><span class="w"> </span><span class="ss">""</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">def</span><span class="w"> </span><span class="n">init</span><span class="p">(</span><span class="n">options</span><span class="p">),</span><span class="w"> </span><span class="nl">do</span><span class="p">:</span><span class="w"> </span><span class="n">options</span>
<span class="w"> </span><span class="n">def</span><span class="w"> </span><span class="k">call</span><span class="p">(</span><span class="o">%</span><span class="n">Plug</span><span class="p">.</span><span class="n">Conn</span><span class="err">{</span><span class="nl">request_path</span><span class="p">:</span><span class="w"> </span><span class="k">path</span><span class="err">}</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">conn</span><span class="p">,</span><span class="w"> </span><span class="n">opts</span><span class="p">)</span><span class="w"> </span><span class="n">do</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="k">path</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">opts</span><span class="o">[</span><span class="n">:paths</span><span class="o">]</span><span class="p">,</span><span class="w"> </span><span class="nl">do</span><span class="p">:</span><span class="w"> </span><span class="n">verify_request</span><span class="err">!</span><span class="p">(</span><span class="n">conn</span><span class="p">.</span><span class="n">params</span><span class="p">,</span><span class="w"> </span><span class="n">opts</span><span class="o">[</span><span class="n">:fields</span><span class="o">]</span><span class="p">)</span>
<span class="w"> </span><span class="n">conn</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">defp</span><span class="w"> </span><span class="n">verify_request</span><span class="err">!</span><span class="p">(</span><span class="n">params</span><span class="p">,</span><span class="w"> </span><span class="n">fields</span><span class="p">)</span><span class="w"> </span><span class="n">do</span>
<span class="w"> </span><span class="n">verified</span><span class="w"> </span><span class="o">=</span>
<span class="w"> </span><span class="n">params</span>
<span class="w"> </span><span class="o">|></span><span class="w"> </span><span class="k">Map</span><span class="p">.</span><span class="n">keys</span><span class="p">()</span>
<span class="w"> </span><span class="o">|></span><span class="w"> </span><span class="n">contains_fields</span><span class="vm">?</span><span class="p">(</span><span class="n">fields</span><span class="p">)</span>
<span class="w"> </span><span class="n">unless</span><span class="w"> </span><span class="n">verified</span><span class="p">,</span><span class="w"> </span><span class="nl">do</span><span class="p">:</span><span class="w"> </span><span class="n">raise</span><span class="p">(</span><span class="n">IncompleteRequestError</span><span class="p">)</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">defp</span><span class="w"> </span><span class="n">contains_fields</span><span class="vm">?</span><span class="p">(</span><span class="n">keys</span><span class="p">,</span><span class="w"> </span><span class="n">fields</span><span class="p">),</span><span class="w"> </span><span class="nl">do</span><span class="p">:</span><span class="w"> </span><span class="n">Enum</span><span class="p">.</span><span class="ow">all</span><span class="vm">?</span><span class="p">(</span><span class="n">fields</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="p">(</span><span class="o">&</span><span class="mi">1</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">keys</span><span class="p">))</span>
<span class="k">end</span>
</code></pre></div>
<p>对应检验请求可以是:</p>
<div class="highlight"><pre><span></span><code><span class="o">$</span><span class="w"> </span><span class="n">curl</span><span class="w"> </span><span class="n">localhost</span><span class="p">:</span><span class="mi">8080</span><span class="o">/</span><span class="n">upload</span><span class="err">?</span><span class="n">content</span><span class="o">=</span><span class="n">foo</span><span class="o">&</span><span class="n">mimetype</span><span class="o">=</span><span class="n">bar</span>
</code></pre></div>
<p>问题是:</p>
<div class="highlight"><pre><span></span><code><span class="o">...</span>
<span class="o">|></span><span class="w"> </span><span class="n">contains_fields</span><span class="o">?(</span><span class="n">fields</span><span class="o">)</span>
</code></pre></div>
<ul>
<li>提供的函式只是对所有 URI 参数键进行检验, 如果缺少了则报错,</li>
<li>可是, 正确请求时, 如何获得所有参数值?</li>
</ul>
<p>先使用输出语句来探查 params 是什么数据类型:</p>
<div class="highlight"><pre><span></span><code>IO.inspect(params)
</code></pre></div>
<p>请求触发后终端输出:</p>
<div class="highlight"><pre><span></span><code><span class="c">%{"cnt" => "foo", "mmt" => "bar"}</span>
</code></pre></div>
<p>是标准 Map 对象.</p>
<h2 id="try">try<a class="headerlink" href="#try" title="Permanent link">¶</a></h2>
<blockquote>
<p>Enum.all?() 是个重要的入口</p>
</blockquote>
<p>追查文档, 知道 Enum 有丰富的序列型数据处置支持:</p>
<blockquote>
<p>Enum.each 可以针对每个键进行附加处置</p>
</blockquote>
<p>所以:</p>
<div class="highlight"><pre><span></span><code><span class="n">defp</span><span class="w"> </span><span class="n">echo_vars</span><span class="p">(</span><span class="n">keys</span><span class="p">,</span><span class="w"> </span><span class="n">fields</span><span class="p">)</span><span class="w"> </span><span class="n">do</span><span class="w"> </span>
<span class="w"> </span><span class="n">Enum</span><span class="o">.</span><span class="n">each</span><span class="p">(</span><span class="n">fields</span><span class="p">,</span><span class="w"> </span><span class="n">fn</span><span class="p">(</span><span class="n">s</span><span class="p">)</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="n">IO</span><span class="o">.</span><span class="n">puts</span><span class="p">(</span><span class="n">s</span><span class="p">)</span><span class="w"> </span><span class="n">end</span><span class="p">)</span>
<span class="w"> </span><span class="n">LOG</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">"chk. as #{keys} ;-)"</span><span class="p">)</span>
<span class="n">end</span>
</code></pre></div>
<p>但是, 各种出错, 因为这时, 传入的 keys 是只有请求 Map 中的键;</p>
<p>那么:</p>
<div class="highlight"><pre><span></span><code><span class="n">Enum</span><span class="p">.</span><span class="n">each</span><span class="p">(</span><span class="n">params</span><span class="p">,</span><span class="n">fn</span><span class="p">(</span><span class="n">k</span><span class="p">)</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="n">IO</span><span class="p">.</span><span class="n">puts</span><span class="p">(</span><span class="nf">Map</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">params</span><span class="p">,</span><span class="n">k</span><span class="p">))</span><span class="w"> </span><span class="kd">end)</span>
</code></pre></div>
<ul>
<li>跳出 verified = params ... 的处理流水线;</li>
<li>直接追加列印处理?</li>
<li>也不行...<ul>
<li>光是看形式就有问题</li>
<li>先对 Map 进行 Enum.each </li>
<li>然后对每一个键, 再进行 Map.get</li>
<li>这简直是对相同的数据进行反复操作</li>
</ul>
</li>
</ul>
<h2 id="hummm">Hummm?!<a class="headerlink" href="#hummm" title="Permanent link">¶</a></h2>
<blockquote>
<p>万万没想到...</p>
</blockquote>
<p>无意中在 <a href="https://mlog.club/article/1923002">如何在Elixir中将映射键从字符串转换为原子 | 码农俱乐部 - Golang中国 - Go语言中文社区</a></p>
<p>看到:</p>
<div class="highlight"><pre><span></span><code>iex(1)> string_key_map = %{"foo" => "bar", "hello" => "world"}
</code></pre></div>
<p>%{"foo" => "bar", "hello" => "world"}</p>
<div class="highlight"><pre><span></span><code><span class="n">iex</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="o">></span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">{</span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="n">val</span><span class="p">}</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">string_key_map</span><span class="p">,</span><span class="w"> </span><span class="n">into</span><span class="p">:</span><span class="w"> </span><span class="c">%{}, do: {String.to_atom(key), val}</span>
<span class="c">%{foo: "bar", hello: "world"}</span>
</code></pre></div>
<p>虽说这是 Comprehensions 概念的通常使用,
但是, 发现, for 这个操作, 和 Python 中的完全一致哪,
于是:</p>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="n">defp</span><span class="w"> </span><span class="n">echo_vars</span><span class="p">(</span><span class="n">params</span><span class="p">)</span><span class="w"> </span><span class="n">do</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">{</span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="n">val</span><span class="p">}</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">params</span><span class="w"> </span><span class="n">do</span>
<span class="w"> </span><span class="c1">#IO.inspect(key)</span>
<span class="w"> </span><span class="c1">#IO.inspect(val)</span>
<span class="w"> </span><span class="n">LOG</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">"each -> #{key}=>#{val} ;-)"</span><span class="p">)</span>
<span class="w"> </span><span class="n">end</span>
<span class="w"> </span><span class="n">end</span>
</code></pre></div>
<p>简直和 Python 中解包行为完全一致...</p>
<p>可是: <a href="https://learnxinyminutes.com/docs/zh-cn/elixir-cn/">Learn elixir in Y Minutes</a>
一句也没提及, for 这么 NB 的操作符哪...</p>
<h2 id="refer">refer.<a class="headerlink" href="#refer" title="Permanent link">¶</a></h2>
<ul>
<li><a href="https://hexdocs.pm/plug/Plug.Router.html">Plug.Router — Plug v1.8.3</a><ul>
<li><a href="http://elixirschool.com/zh-hans/lessons/specifics/plug/">Plug · Elixir School</a></li>
</ul>
</li>
<li><a href="https://mlog.club/article/1923002">如何在Elixir中将映射键从字符串转换为原子</a><ul>
<li><a href="https://szpzs.oschina.io/2017/02/11/elixir-getting-started-comprehensions/">Elixir入门教程-速构 | Time is all</a></li>
</ul>
</li>
</ul>
<h2 id="changelog">Changelog<a class="headerlink" href="#changelog" title="Permanent link">¶</a></h2>
<ul>
<li>200109 .5h 配置模板,重新发布</li>
<li>200108 .5h 输出</li>
<li>200107 2.5h 折腾</li>
</ul>Leo 第N次科普2019-08-23T00:00:00+08:002019-09-08T12:44:51+08:00Zoom.Quiettag:blog.zoomquiet.io,2019-08-23:/leo-101-againnn.html
<h2 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p><a href="https://wewe.t9t.io/chat/%E3%80%90%E9%9B%86%E6%99%BA%E3%80%91%E6%B3%A8%E6%84%8F%E5%8A%9B%E4%B8%8E%E7%9F%A5%E8%AF%86%E7%AE%A1%E7%90%86%E7%BE%A4">[集智]注意力与知识管理群</a></p>
<p>中大家经常就一些工具产生各种讨论,
俺一向的标签是:</p>
<ul>
<li>Python</li>
<li>Pythonic</li>
<li><a href="http://www.leoeditor.com/">Leo</a></li>
</ul>
<p>其它还好, 有广泛群众基础 …</p>
<h2 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p><a href="https://wewe.t9t.io/chat/%E3%80%90%E9%9B%86%E6%99%BA%E3%80%91%E6%B3%A8%E6%84%8F%E5%8A%9B%E4%B8%8E%E7%9F%A5%E8%AF%86%E7%AE%A1%E7%90%86%E7%BE%A4">[集智]注意力与知识管理群</a></p>
<p>中大家经常就一些工具产生各种讨论,
俺一向的标签是:</p>
<ul>
<li>Python</li>
<li>Pythonic</li>
<li><a href="http://www.leoeditor.com/">Leo</a></li>
</ul>
<p>其它还好, 有广泛群众基础, 这个 Leo 就经常引发嗯哼</p>
<h2 id="_2">引子:<a class="headerlink" href="#_2" title="Permanent link">¶</a></h2>
<blockquote>
<p>pimgeek-知识管理工具研究者: 插一个技术提问. . . </p>
</blockquote>
<ul>
<li>@大妈🙊Zoom.Quiet LeoEditor 的节点支持类似 {{ var }} 这样的模板语法吗?<ul>
<li>我知道 << section >> 这样的用法,还有 valuespace + jinja 的方式, 不知还有没有其它实现方式?[疑问] '</li>
<li><< section >> 这种用法是 LeoEditor 内置的实现方式</li>
<li>{{ var }} 这种用法是 LeoEditor 插件的实现方式</li>
</ul>
</li>
<li>我就是希望定义一些可填充的内容,把这些内容从代码主体中抽取出来,这样我编辑起来方便. '<ul>
<li>有些内容,比如网页里的作者信息等,一次编辑后反复引用. 修改时也方便. </li>
<li>专业的 Web 开发者应该是把这些代码拆成多个文件来管理. 我现在尝试用一个 LeoEditor 的大纲文件来管理. '</li>
</ul>
</li>
<li><< section >> 的用法也是类似的,只不过它必须是模板节点的子节点. '<ul>
<li>这样不必对每个节点都执行特殊操作,最省心. '</li>
<li>如果需要复用比如 html-header 中的信息,我可以利用 clone 节点的方式. '</li>
</ul>
</li>
</ul>
<blockquote>
<p>tomz-没有褒贬: 发现leo把tangle命令去掉了. 只能命令行输入tangle. 没有尝试成功怎么用尖括号引用父节点. 找不到文档了. '
noweb和org这种没有outline结构的软件就能任意引用任何节点. '
tomz-没有褒贬: 对啊 原来用tangle命令就能引用父节点 等于是全局变量 '
tangle才是真正的noweb方式 现在只能子节点有了局限 '</p>
<p>pimgeek-知识管理工具研究者: @tomz-没有褒贬 我昨天已经实现自己的想法了,虽然没有 tangle 没有全局变量,可能会稍微麻烦一些. </p>
</blockquote>
<ul>
<li>我现在是这样,如果有需要被反复引用的代码段 S,我会先放在一个专门收集这类代码的大纲节点下. </li>
<li>后面但凡有代码 X 需要用到时,我就在 X 下方创建一个 S 的 clone 子节点,然后在 X 中使用 << S >> 引用之. 😄 '</li>
<li>如果我发现 S 代码段,暂时对 X 没有帮助了, 我也不用把这个 clone 节点删除, 只要把那个 << S >> 从代码 X 中移除掉就可以了 😎 '</li>
<li>所以 Leo Editor 的 clone 节点是个好东西啊 [耶] '</li>
</ul>
<blockquote>
<p>大妈🙊Zoom.Quiet: 才发现?
俺宣传了有14年了...没人相信, 这是最好的重构姿势... '</p>
</blockquote>
<ul>
<li>pimgeek-知识管理工具研究者: 不是我不相信,而是以往的开发需求没被明晰化,更早以前则不知道 Leo Editor 😂 '<ul>
<li>2016 年关于 Leo Editor 的讨论 '</li>
<li>理论上可以把个人的所有开发代码都这样管理起来:<ul>
<li>网上发布用 Git, 本地管理用 Leo, </li>
<li>互不干扰</li>
<li>(Leo 大纲可以自动生成带有特殊注释的代码文件, 文件发生变化时也能同步回 Leo 里 )互不干扰.</li>
</ul>
</li>
</ul>
</li>
</ul>
<blockquote>
<p>𝙰𝚣𝚎𝚛𝚒𝚕: 这是大妈的上古神器系列的... '</p>
<p>大妈🙊Zoom.Quiet: 是也乎 ╮(╯▽╰)╭</p>
</blockquote>
<p>@pimgeek-知识管理工具研究者 --> 那都是老黄历了</p>
<div class="highlight"><pre><span></span><code>现在 Leo 有了更好的算子
~可以不污染输入又确保双向感知了~ '
</code></pre></div>
<blockquote>
<p>pimgeek-知识管理工具研究者: 我集中问一下: </p>
</blockquote>
<ul>
<li>
<ol>
<li>有什么比 @file 更好的方式, 可以双向感知?</li>
</ol>
</li>
<li>
<ol>
<li>有什么比 << section >> 更好的方式, 可以实现代码段引用? '</li>
</ol>
</li>
</ul>
<blockquote>
<p>' 大妈🙊Zoom.Quiet: 代码引用 --> 这是高德纳原创发明~比宏直觉又简洁~含自注释~
多用~没毛病 '</p>
<p>pimgeek-知识管理工具研究者: @file 节点我去看文档, 但是问题 2 我真没找到, 可能我搜索方式不对, 昨天至少花了 3 个小时找替代, 就是没找到. '</p>
</blockquote>
<ul>
<li>大妈🙊Zoom.Quiet: <a href="http://www.leoeditor.com/directives.html">Directives Reference — Leo 6.0 documentation</a><ul>
<li>之前是用 @nosent 替代 @file 的<ul>
<li>后来找到自动 diff 并双向合并技术后</li>
<li>就有了 @auto @clean</li>
</ul>
</li>
<li>一次性将 混入/出 时依赖的标记文本从目标文本中清除了 '</li>
</ul>
</li>
<li>所以, 作为 Leo 老用户, 从来不看官方文档,<ul>
<li>导致一直用老经验使用效率有问题的流程...</li>
<li>那么, 推而广之, 可能其它工具也都有类似问题存在//// '</li>
</ul>
</li>
</ul>
<blockquote>
<p>' 大妈🙊Zoom.Quiet: ' pimgeek-知识管理工具研究者: 大多数文档中的例子和提问/设问相对较少, 如果能多一些例子和提问/设问就好多了. '</p>
</blockquote>
<p>看 FAQ ....</p>
<div class="highlight"><pre><span></span><code>官方文档很多都是从代码自动生成,
难免呆板,
所以, FAQ 中有灵活自然的问答...
甚至于, 都是开源项目哪,
你哪儿不舒服, 问哪.... '
</code></pre></div>
<blockquote>
<p>pimgeek-知识管理工具研究者: LeoEditor 似乎没有规定源码的组织方式,如果要批量导入,可能还是先在自己头脑中预先想好一种结构,而不是依赖它的"内置结构" ... '</p>
<p>@SML 似乎不行,他的大纲树 和 硬盘的路径树 是两个东西</p>
</blockquote>
<h2 id="_3">断言:<a class="headerlink" href="#_3" title="Permanent link">¶</a></h2>
<blockquote>
<p>SML: 嗯嗯 所以不太适合开发flask这种组织好的工程项目',更适合学习,归类,阅读代码,或者开发小型项目 '</p>
<p>额,大家可能误会我意思了 '
我并不是批判leoeditor '
他确实不适合,类似laravel,flask这种成熟的工程项目开发 '
django项目的文件超过数百个了 '
连批量导入都不支持... '</p>
<p>我明白你说的,就是用大纲的形式串起来,当做模板语言的使用 '
这个我清楚,leo的思想是想以类,或者组件为单位 '
这不就是 前端的经常用的组建化开发 或者模板语法么... '</p>
<p>@SML 这个....作为 ide 使用啊 '
你可以尝试一下,用它来开发django,或flask 基本是不可能的 '</p>
</blockquote>
<p>大妈🙊Zoom.Quiet: 该批就批~俺又不是 Leo 厂商代理~</p>
<ul>
<li>问题是不说问题 --> 只给大家你的方案... 没法儿聊啊~ '<ul>
<li>就算是ide 也和批量导入文件无关啊 --> 你想干什么?真正的? '</li>
<li>关键为什么大家习惯性讨论问题的某个方案 --> 而不讨论问题本身呢?</li>
<li>批量导入工程是为什么啊? '</li>
</ul>
</li>
<li>俺用 Leo 14年了~<ul>
<li>从服务端 web server / DevOps 管理/数据分析~到 chrome 插件开发... golang 单体服务 --> Qt 桌面应用... bottle dango flask ....</li>
<li>基本上凡涉及文件越过三个的都用 leo 管理了... </li>
</ul>
</li>
<li>Leo 没有自动重构<ul>
<li>没有自动跳类定义... </li>
<li>没有您依赖的一切 IDE 功能~</li>
<li>但并不影响开发任何想开发的软件~</li>
</ul>
</li>
<li>因为... <ul>
<li>IDE 从 TurboC之后俺再没用过任何一种... </li>
<li>VSCode 也关闭或不用任何 IDE 特有功能... </li>
<li>所以... 没理解你说的不合适在哪个功能上? '</li>
</ul>
</li>
<li>俺通过 Leo 管理的文件过千了... '</li>
</ul>
<blockquote>
<p>SML: 编辑哪个就导入哪个...好吧 你解答了我的疑惑 '</p>
<blockquote>
<p>pimgeek-知识管理工具研究者: '我:如果想把手头现有的,已经用传统项目结构组织好的代码,转换为 Leo Editor 的"树状网结构",那可能是一项浩大的工程...
与放弃 pyCharm 转投 VS.Code 那种变化相比,肯定是不一样,要麻烦的多. '
' SML: 这个我清楚,leo的思想是想以类,或者组件为单位 '
' tomz-没有褒贬: 不是类和组件为单位 单位可以是一个函数其中的几行 '
如果不是说代码内部的组织 那就是说对文件之上层次的组织了 '
将几行作为单位 等于是为这几行做了一个注释 同时就将这几行折叠起来了 '</p>
</blockquote>
</blockquote>
<p>大妈🙊Zoom.Quiet: 也不是~</p>
<ul>
<li>Leo 可抽象管理的 note 从几行到几个文件夹... 都可以~ '</li>
</ul>
<blockquote>
<p>' SML: 嗯嗯 就是想以 snippet 为单位吧 '</p>
</blockquote>
<p>大妈🙊Zoom.Quiet: 更加不是~~~~ '</p>
<ul>
<li>如果你写过小说就懂了 '</li>
</ul>
<blockquote>
<p>@tomz-没有褒贬: 文学编程就是让代码更整齐更帅 😂 '
换个词 叫一目了然 '</p>
</blockquote>
<p><code>是也乎,( ̄▽ ̄)</code></p>
<div class="highlight"><pre><span></span><code>Yes and Not;
</code></pre></div>
<p>文学化编辑器, 正好不怎么关心最终输出的代码是否整齐/帅</p>
<ul>
<li>但是, 一目了然, 的确是真的...</li>
<li>只是, 只针对作者本人...</li>
<li>为什么这么说 '<ul>
<li>@pimgeek-知识管理工具研究者 发现并研究以及尝试整合的,也从无一个主流工具/软件,</li>
<li>为什么?原因相似...</li>
</ul>
</li>
<li>可惜, 世人从来不关心自己被浪费掉的时间和精力...<ul>
<li>一脑门子 WYSIWYG 要求,</li>
<li>全然无视了在计算机发展过程中, 最宝贵的从来不是视觉要求,</li>
<li>而是思想要求 '</li>
</ul>
</li>
<li>Django 或是 Flask 工程, 之所以, 会有多个目录和很多文件;<ul>
<li>是框架本身引导和要求的?为什么?</li>
<li>因为框架是领域工程经验集成, 要求我们必须按照人家的工程经验走... </li>
<li>凡是上点儿规模的工程, 一个共同经验就是:<ul>
<li><strong>目录即系统架构</strong></li>
</ul>
</li>
<li>目录结构以及命名以及文件分布约定本身,</li>
<li>就决定了系统依赖/功能/数据/调运/... 内部架构;</li>
</ul>
</li>
<li>但是, 正如小说撰写, 虽然最终是由/字/词/句/段落/章节构成了小说,<ul>
<li>可小说真正想传达的意象, 叙述结构, </li>
<li>却正好超脱这些最终产物的, </li>
<li>而是萦绕在作者头脑内心深处的另外结构;</li>
</ul>
</li>
<li>当初为了和 C 初始人们提倡的结构化编辑叫劲儿,<ul>
<li>高老爷创造的文学化编程, </li>
<li>就是抓住了这一更加 Bigger 的思想, <ul>
<li>完成了专用 DSL -> WEB 以及对应方言 CWEB;</li>
</ul>
</li>
<li>可以在 变量/语句/函式/类/文件/目录 之上,</li>
<li>描述工程师对系统真正的理解和结构;</li>
</ul>
</li>
<li>但是, 为什么现在 "所有人" 用的各种 IDE 都没有这种支持?<ul>
<li>原因非常简单, 因为 IDE 所包含的工程思想, 是最平庸简单的,</li>
<li>是能为最大多数快速理解并使用的,</li>
<li>甚至于连商务人员都能理解和宣传的;</li>
</ul>
</li>
<li>可惜, 编程是门手艺活,<ul>
<li>每个手艺人都有自己的个性和习惯,</li>
<li>真正注意到自己习惯和个性的手艺人, 一定是从工具开始自行构造的;</li>
<li>这也是为什么 Plan9 小组, 大家使用的 ACM 是针对三键鼠标优化的,</li>
<li>所有功能集成在中键点击菜单中, </li>
<li>根本不兼容任何 IDE 的主要功能;</li>
</ul>
</li>
<li>即, 编程, 这么私人的事儿,<ul>
<li>如果工具不能充分匹配或是定制匹配,</li>
<li>那么, 就只能被迫将自己训化为现有流行工具包含的工程思想/编程习惯/思维...</li>
<li>当然, 多数人将之视为理所当然, 完全无视了这过程中,</li>
<li>自己被主动无形中格式化掉的个性和思想;</li>
</ul>
</li>
<li>简单说, 商业社会中, 主流产品一定不是最优的,<ul>
<li>毕竟主流产品一定得是利润最好的...</li>
<li>所以, 美军手中武器一定是最便宜的那种...</li>
</ul>
</li>
<li>软件行业更加是:<ul>
<li>XP 统治PC 多年,<ul>
<li>为什么最后还是给放弃了?</li>
</ul>
</li>
<li>JAVA 这么多人吐糟, 连创始人都退出维护团队了,<ul>
<li>为什么, 照样是商用软件C位选择?</li>
</ul>
</li>
<li>但是, NASA 照样用古老的LISP ?</li>
</ul>
</li>
</ul>
<p>...</p>
<blockquote>
<p>' tomz-没有褒贬: leo本身的代码就是例子 leo是吃自己的狗食的 '</p>
</blockquote>
<h3 id="_4">文学化:<a class="headerlink" href="#_4" title="Permanent link">¶</a></h3>
<blockquote>
<p>' 𝙰𝚣𝚎𝚛𝚒𝚕: 印象中 大妈貌似还认识 Leo 编辑器的开发者老爷子吧 '</p>
</blockquote>
<p>大妈🙊Zoom.Quiet: http://0.zoomquiet.top/pychina/PyCon2013China/PyConChina2013-EKR-final-v2.mp4</p>
<p><-- 是也乎 ╮(╯▽╰)╭</p>
<p>作者本人介绍 Leo
可参考理解... '</p>
<blockquote>
<p>@tomz-没有褒贬 leo所做的工作只是把一个文件的一些行折叠为一个代码块 所以我觉得可以用emacs的folding程序代替
先写文档后写代码我没有尝试过 '</p>
</blockquote>
<p><code>是也乎 ╮(╯▽╰)╭</code></p>
<p>正好理解反了~ '</p>
<p>俺也没尝试过... 文学化编辑... 洽洽和文档无关~ '
也都关联不大
--> 文学化编辑和以往结构化编辑是根本性不同的思想 --> 最大阻碍是思维惯性... '</p>
<h2 id="_5">分析<a class="headerlink" href="#_5" title="Permanent link">¶</a></h2>
<p>一定要找一个生活化的案例, 可能就是:</p>
<ul>
<li>刚刚来到中国的西方探险家, 一定无法理解为如何用筷子叉起食物?</li>
<li>被 IDE 训化的绝大多数程序猿, <ul>
<li>早已忘记了写代码时自己是怎么思考的</li>
<li>而是替之以 IDE 要求我们如何去写的</li>
</ul>
</li>
<li>这样其实, 并没什么不好<ul>
<li>毕竟, 公司不关心, 代码是怎么生产出来的</li>
</ul>
</li>
<li>这就好比, 被卖猪仔到美国的华工<ul>
<li>如果想融入当地<ul>
<li>要作的事儿, 可能就是丢指筷子,剪指头发</li>
<li>永远不再吃米饭/炒菜, 在一切细节上伪装成周围的人</li>
<li>直到最后从思想上也同化</li>
</ul>
</li>
<li>才可能被美国人视作长的实在丑的人<ul>
<li>而不是吃死老鼠的黄种鸡</li>
</ul>
</li>
</ul>
</li>
<li>其实, 类似 Leo 这样设计思想和 IDE 完全不同的编辑环境非常多:<ul>
<li>神之编辑器 ~ Emacs</li>
<li>编辑器之神 ~ Vim</li>
<li>行编辑器 ~ le</li>
<li>...</li>
</ul>
</li>
<li>那么多尝试吧, 找到自己最喜欢的那种...</li>
</ul>
<h2 id="_6">回顾<a class="headerlink" href="#_6" title="Permanent link">¶</a></h2>
<blockquote>
<p>其实, 俺当年也用了将近一年, 才慢慢明白过来的:</p>
</blockquote>
<p>其实, 和其它全新技能一样,</p>
<ul>
<li>先熟悉工具内置功能</li>
<li>然后, 结合具体任务</li>
<li>完成基本行为的肌肉记忆后</li>
<li>才可能进一步完成以往用 IDE 才能完成任务的文学化再流程...</li>
</ul>
<p>很多时候, 和 IDE 的感觉有点儿象:</p>
<ul>
<li>手工绘画和打印槐打印一张图片的差别</li>
<li>Leo 是响应自然的思考和尝试过程<ul>
<li>将最终代码/文档的形成从目标形式中抽离了</li>
<li>以提纲为主要结构</li>
<li>每次时应对 node 中非常小的几行内容</li>
</ul>
</li>
<li>不象 IDE 无时不刻在整体分析/提醒你应该作什么</li>
</ul>
<h2 id="refer">refer.<a class="headerlink" href="#refer" title="Permanent link">¶</a></h2>
<p>以往也用自己的方式尝试解释过:</p>
<ul>
<li><a href="http://s5.zoomquiet.top/060730-abtLeo/index.html">啄木鸟/CPUG 会课06年度第九次 (built by S5)</a></li>
<li><a href="http://s5.zoomquiet.top/131101-leo-china/index.html">Leo ~ 文学式编程体验</a></li>
<li><a href="http://s5.zoomquiet.top/131113-MyTools/index.html">我的工具箱</a></li>
<li>...</li>
</ul>
<p>相关录音:</p>
<ul>
<li><a href="http://org.up.zoomquiet.top/ztapes/wav4zoomq/060730-cpug_abt-leo.ogg">060730-cpug_abt-leo.ogg</a></li>
<li><a href="http://org.up.zoomquiet.top/ztapes/wav4zoomq/100716-Leo-LiterateProgramming/">100716-Leo-LiterateProgramming/</a></li>
<li><a href="http://org.up.zoomquiet.top/ztapes/wav4zoomq/100930-snda-mytools/">100930-snda-mytools/</a></li>
<li>...</li>
</ul>修复 subl3 包安装2019-04-03T12:12:00+08:002019-04-03T12:47:58+08:00Zoom.Quiettag:blog.zoomquiet.io,2019-04-03:/fix-subl-package-installation.html
<h2 id="bg">BG<a class="headerlink" href="#bg" title="Permanent link">¶</a></h2>
<p>突然: <code>cmd+shift+P</code> 选择 <code>Package Control: install package</code> 时,一直:</p>
<blockquote>
<blockquote>
<blockquote>
<p>There are no packages available for installation</p>
</blockquote>
</blockquote>
</blockquote>
<h2 id="goal">goal<a class="headerlink" href="#goal" title="Permanent link">¶</a></h2>
<p>当然就是解决呗:</p>
<ul>
<li>各种官方都有吼</li>
<li><a href="https://packagecontrol.io/docs/troubleshooting">Troubleshooting - Package Control</a></li>
<li><a href="https://github.com/wbond/package_control/issues/959#issuecomment-168447848">There are no packages available for installation - Package Control of …</a></li></ul>
<h2 id="bg">BG<a class="headerlink" href="#bg" title="Permanent link">¶</a></h2>
<p>突然: <code>cmd+shift+P</code> 选择 <code>Package Control: install package</code> 时,一直:</p>
<blockquote>
<blockquote>
<blockquote>
<p>There are no packages available for installation</p>
</blockquote>
</blockquote>
</blockquote>
<h2 id="goal">goal<a class="headerlink" href="#goal" title="Permanent link">¶</a></h2>
<p>当然就是解决呗:</p>
<ul>
<li>各种官方都有吼</li>
<li><a href="https://packagecontrol.io/docs/troubleshooting">Troubleshooting - Package Control</a></li>
<li><a href="https://github.com/wbond/package_control/issues/959#issuecomment-168447848">There are no packages available for installation - Package Control of Sublime Text 3 · Issue #959 · wbond/package_control</a></li>
<li>...</li>
</ul>
<h2 id="logging">logging<a class="headerlink" href="#logging" title="Permanent link">¶</a></h2>
<p>打开 debug 观察:</p>
<div class="highlight"><pre><span></span><code><span class="n">Package</span><span class="w"> </span><span class="n">Control</span><span class="p">:</span><span class="w"> </span><span class="n">Skipping</span><span class="w"> </span><span class="n">automatic</span><span class="w"> </span><span class="n">upgrade</span><span class="p">,</span><span class="w"> </span><span class="n">last</span><span class="w"> </span><span class="n">run</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="mi">2019</span><span class="o">-</span><span class="mi">04</span><span class="o">-</span><span class="mi">03</span><span class="w"> </span><span class="mi">11</span><span class="p">:</span><span class="mi">45</span><span class="p">:</span><span class="mi">00</span><span class="p">,</span><span class="w"> </span><span class="n">next</span><span class="w"> </span><span class="n">run</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="mi">2019</span><span class="o">-</span><span class="mi">04</span><span class="o">-</span><span class="mi">03</span><span class="w"> </span><span class="mi">12</span><span class="p">:</span><span class="mi">45</span><span class="p">:</span><span class="mi">00</span><span class="w"> </span><span class="ow">or</span><span class="w"> </span><span class="n">after</span>
<span class="n">Detected</span><span class="w"> </span><span class="n">ASCII</span><span class="w"> </span><span class="n">vs</span><span class="w"> </span><span class="n">Undefined</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="mi">100</span><span class="o">%</span><span class="w"> </span><span class="n">confidence</span>
<span class="n">Package</span><span class="w"> </span><span class="n">Control</span><span class="p">:</span><span class="w"> </span><span class="n">Fetching</span><span class="w"> </span><span class="n">list</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">available</span><span class="w"> </span><span class="n">packages</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">dependencies</span>
<span class="w"> </span><span class="n">Platform</span><span class="p">:</span><span class="w"> </span><span class="n">osx</span><span class="o">-</span><span class="n">x64</span>
<span class="w"> </span><span class="n">Sublime</span><span class="w"> </span><span class="n">Text</span><span class="w"> </span><span class="n">Version</span><span class="p">:</span><span class="w"> </span><span class="mi">3200</span>
<span class="w"> </span><span class="n">Package</span><span class="w"> </span><span class="n">Control</span><span class="w"> </span><span class="n">Version</span><span class="p">:</span><span class="w"> </span><span class="mf">3.3</span><span class="o">.</span><span class="mi">0</span>
<span class="n">Package</span><span class="w"> </span><span class="n">Control</span><span class="p">:</span><span class="w"> </span><span class="n">Download</span><span class="w"> </span><span class="n">Debug</span>
<span class="w"> </span><span class="n">URL</span><span class="p">:</span><span class="w"> </span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">packagecontrol</span><span class="o">.</span><span class="n">io</span><span class="o">/</span><span class="n">channel_v3</span><span class="o">.</span><span class="n">json</span>
<span class="w"> </span><span class="n">Timeout</span><span class="p">:</span><span class="w"> </span><span class="mi">30</span>
<span class="w"> </span><span class="n">Resolved</span><span class="w"> </span><span class="n">IP</span><span class="p">:</span><span class="w"> </span><span class="mf">74.207</span><span class="o">.</span><span class="mf">232.232</span>
<span class="w"> </span><span class="n">Resolved</span><span class="w"> </span><span class="n">IPv6</span><span class="p">:</span><span class="w"> </span><span class="mi">2600</span><span class="p">:</span><span class="mi">3</span><span class="n">c02</span><span class="p">::</span><span class="n">f03c</span><span class="p">:</span><span class="mi">91</span><span class="n">ff</span><span class="p">:</span><span class="n">fec5</span><span class="p">:</span><span class="mi">4</span><span class="n">fd5</span>
<span class="n">Package</span><span class="w"> </span><span class="n">Control</span><span class="p">:</span><span class="w"> </span><span class="n">Urllib</span><span class="w"> </span><span class="n">Debug</span><span class="w"> </span><span class="n">Proxy</span>
<span class="w"> </span><span class="n">http_proxy</span><span class="p">:</span><span class="w"> </span>
<span class="w"> </span><span class="n">https_proxy</span><span class="p">:</span><span class="w"> </span>
<span class="w"> </span><span class="n">proxy_username</span><span class="p">:</span><span class="w"> </span>
<span class="w"> </span><span class="n">proxy_password</span><span class="p">:</span><span class="w"> </span>
<span class="n">Package</span><span class="w"> </span><span class="n">Control</span><span class="p">:</span><span class="w"> </span><span class="n">Found</span><span class="w"> </span><span class="n">previously</span><span class="w"> </span><span class="n">exported</span><span class="w"> </span><span class="n">CA</span><span class="w"> </span><span class="n">bundle</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="o">/</span><span class="n">Users</span><span class="o">/</span><span class="n">zoomq</span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Application</span><span class="w"> </span><span class="n">Support</span><span class="o">/</span><span class="n">Sublime</span><span class="w"> </span><span class="n">Text</span><span class="w"> </span><span class="mi">3</span><span class="o">/</span><span class="n">Packages</span><span class="o">/</span><span class="n">User</span><span class="o">/</span><span class="n">oscrypto</span><span class="o">-</span><span class="n">ca</span><span class="o">-</span><span class="n">bundle</span><span class="o">.</span><span class="n">crt</span><span class="w"> </span><span class="p">(</span><span class="mi">268761</span><span class="w"> </span><span class="n">bytes</span><span class="p">)</span>
<span class="n">Package</span><span class="w"> </span><span class="n">Control</span><span class="p">:</span><span class="w"> </span><span class="n">Urllib</span><span class="w"> </span><span class="n">HTTPS</span><span class="w"> </span><span class="n">Debug</span><span class="w"> </span><span class="n">General</span>
<span class="w"> </span><span class="n">Connecting</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">packagecontrol</span><span class="o">.</span><span class="n">io</span><span class="w"> </span><span class="n">on</span><span class="w"> </span><span class="n">port</span><span class="w"> </span><span class="mi">443</span>
<span class="n">Package</span><span class="w"> </span><span class="n">Control</span><span class="p">:</span><span class="w"> </span><span class="n">Error</span><span class="w"> </span><span class="n">downloading</span><span class="w"> </span><span class="n">channel</span><span class="o">.</span><span class="w"> </span><span class="n">URL</span><span class="w"> </span><span class="n">error</span><span class="w"> </span><span class="p">[</span><span class="n">Errno</span><span class="w"> </span><span class="mi">65</span><span class="p">]</span><span class="w"> </span><span class="n">No</span><span class="w"> </span><span class="n">route</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">host</span><span class="w"> </span><span class="n">downloading</span><span class="w"> </span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">packagecontrol</span><span class="o">.</span><span class="n">io</span><span class="o">/</span><span class="n">channel_v3</span><span class="o">.</span><span class="n">json</span><span class="o">.</span>
</code></pre></div>
<p>果断就是 <code>https://packagecontrol.io/channel_v3.json</code> 资源无法访问;</p>
<p>尝试配置 host 无果;
也升级 <code>Package Control</code> 本身;</p>
<p>看来是和谐了? 那么:</p>
<ul>
<li>翻越, 下载</li>
<li>发布为 http://101.zoomquiet.top/res/subl/channel_v3.json</li>
<li>配置到 <code>Package Control.sublime-settings</code><ul>
<li>Preferences > Package Settings > Package Control > Settings - User</li>
</ul>
</li>
</ul>
<p>追加为:</p>
<div class="highlight"><pre><span></span><code>"channels": [
"http://101.zoomquiet.top/res/subl/channel_v3.json"
],
</code></pre></div>
<p>再来就好了:</p>
<div class="highlight"><pre><span></span><code><span class="n">Package</span><span class="w"> </span><span class="n">Control</span><span class="p">:</span><span class="w"> </span><span class="n">Fetching</span><span class="w"> </span><span class="n">list</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">available</span><span class="w"> </span><span class="n">packages</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">dependencies</span>
<span class="w"> </span><span class="n">Platform</span><span class="p">:</span><span class="w"> </span><span class="n">osx</span><span class="o">-</span><span class="n">x64</span>
<span class="w"> </span><span class="n">Sublime</span><span class="w"> </span><span class="n">Text</span><span class="w"> </span><span class="n">Version</span><span class="p">:</span><span class="w"> </span><span class="mi">3200</span>
<span class="w"> </span><span class="n">Package</span><span class="w"> </span><span class="n">Control</span><span class="w"> </span><span class="n">Version</span><span class="p">:</span><span class="w"> </span><span class="mf">3.3</span><span class="o">.</span><span class="mi">0</span>
<span class="n">Package</span><span class="w"> </span><span class="n">Control</span><span class="p">:</span><span class="w"> </span><span class="n">Download</span><span class="w"> </span><span class="n">Debug</span>
<span class="w"> </span><span class="n">URL</span><span class="p">:</span><span class="w"> </span><span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="mf">101.</span><span class="n">zoomquiet</span><span class="o">.</span><span class="n">top</span><span class="o">/</span><span class="n">res</span><span class="o">/</span><span class="n">subl</span><span class="o">/</span><span class="n">channel_v3</span><span class="o">.</span><span class="n">json</span>
<span class="w"> </span><span class="n">Timeout</span><span class="p">:</span><span class="w"> </span><span class="mi">30</span>
<span class="w"> </span><span class="n">Resolved</span><span class="w"> </span><span class="n">IP</span><span class="p">:</span><span class="w"> </span><span class="mf">183.236</span><span class="o">.</span><span class="mf">31.251</span>
<span class="n">Package</span><span class="w"> </span><span class="n">Control</span><span class="p">:</span><span class="w"> </span><span class="n">Urllib</span><span class="w"> </span><span class="n">Debug</span><span class="w"> </span><span class="n">Proxy</span>
<span class="w"> </span><span class="n">http_proxy</span><span class="p">:</span><span class="w"> </span>
<span class="w"> </span><span class="n">https_proxy</span><span class="p">:</span><span class="w"> </span>
<span class="w"> </span><span class="n">proxy_username</span><span class="p">:</span><span class="w"> </span>
<span class="w"> </span><span class="n">proxy_password</span><span class="p">:</span><span class="w"> </span>
<span class="n">Package</span><span class="w"> </span><span class="n">Control</span><span class="p">:</span><span class="w"> </span><span class="n">Urllib</span><span class="w"> </span><span class="n">HTTP</span><span class="w"> </span><span class="n">Debug</span><span class="w"> </span><span class="n">General</span>
<span class="w"> </span><span class="n">Connecting</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="mf">101.</span><span class="n">zoomquiet</span><span class="o">.</span><span class="n">top</span><span class="w"> </span><span class="n">on</span><span class="w"> </span><span class="n">port</span><span class="w"> </span><span class="mi">80</span>
<span class="n">Package</span><span class="w"> </span><span class="n">Control</span><span class="p">:</span><span class="w"> </span><span class="n">Urllib</span><span class="w"> </span><span class="n">HTTP</span><span class="w"> </span><span class="n">Debug</span><span class="w"> </span><span class="n">Write</span>
<span class="w"> </span><span class="n">GET</span><span class="w"> </span><span class="o">/</span><span class="n">res</span><span class="o">/</span><span class="n">subl</span><span class="o">/</span><span class="n">channel_v3</span><span class="o">.</span><span class="n">json</span><span class="w"> </span><span class="n">HTTP</span><span class="o">/</span><span class="mf">1.1</span>
<span class="w"> </span><span class="n">User</span><span class="o">-</span><span class="n">Agent</span><span class="p">:</span><span class="w"> </span><span class="n">Package</span><span class="w"> </span><span class="n">Control</span><span class="w"> </span><span class="n">v3</span><span class="o">.</span><span class="mf">3.0</span>
<span class="w"> </span><span class="n">Connection</span><span class="p">:</span><span class="w"> </span><span class="n">Keep</span><span class="o">-</span><span class="n">Alive</span>
<span class="w"> </span><span class="n">Host</span><span class="p">:</span><span class="w"> </span><span class="mf">101.</span><span class="n">zoomquiet</span><span class="o">.</span><span class="n">top</span>
<span class="w"> </span><span class="n">Accept</span><span class="o">-</span><span class="n">Encoding</span><span class="p">:</span><span class="w"> </span><span class="n">bzip2</span><span class="p">,</span><span class="n">gzip</span><span class="p">,</span><span class="n">deflate</span>
<span class="n">Package</span><span class="w"> </span><span class="n">Control</span><span class="p">:</span><span class="w"> </span><span class="n">Urllib</span><span class="w"> </span><span class="n">HTTP</span><span class="w"> </span><span class="n">Debug</span><span class="w"> </span><span class="n">Read</span>
<span class="w"> </span><span class="n">HTTP</span><span class="o">/</span><span class="mf">1.1</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="n">OK</span>
<span class="w"> </span><span class="n">Server</span><span class="p">:</span><span class="w"> </span><span class="n">marco</span><span class="o">/</span><span class="mf">2.9</span>
<span class="w"> </span><span class="n">Date</span><span class="p">:</span><span class="w"> </span><span class="n">Wed</span><span class="p">,</span><span class="w"> </span><span class="mi">03</span><span class="w"> </span><span class="n">Apr</span><span class="w"> </span><span class="mi">2019</span><span class="w"> </span><span class="mi">04</span><span class="p">:</span><span class="mi">34</span><span class="p">:</span><span class="mi">47</span><span class="w"> </span><span class="n">GMT</span>
<span class="w"> </span><span class="n">Content</span><span class="o">-</span><span class="n">Type</span><span class="p">:</span><span class="w"> </span><span class="n">application</span><span class="o">/</span><span class="n">json</span>
<span class="w"> </span><span class="n">Transfer</span><span class="o">-</span><span class="n">Encoding</span><span class="p">:</span><span class="w"> </span><span class="n">chunked</span>
<span class="w"> </span><span class="n">Connection</span><span class="p">:</span><span class="w"> </span><span class="n">keep</span><span class="o">-</span><span class="n">alive</span>
<span class="w"> </span><span class="n">Vary</span><span class="p">:</span><span class="w"> </span><span class="n">Accept</span><span class="o">-</span><span class="n">Encoding</span>
<span class="w"> </span><span class="n">X</span><span class="o">-</span><span class="n">Source</span><span class="p">:</span><span class="w"> </span><span class="n">C</span><span class="o">/</span><span class="mi">200</span>
<span class="w"> </span><span class="n">Content</span><span class="o">-</span><span class="n">Disposition</span><span class="p">:</span><span class="w"> </span><span class="n">inline</span><span class="p">;</span><span class="w"> </span><span class="n">filename</span><span class="o">=</span><span class="s2">"channel_v3.json"</span><span class="p">;</span><span class="w"> </span><span class="n">filename</span><span class="o">*=</span><span class="n">utf</span><span class="o">-</span><span class="mi">8</span><span class="s1">' '</span><span class="n">channel_v3</span><span class="o">.</span><span class="n">json</span>
<span class="w"> </span><span class="n">X</span><span class="o">-</span><span class="n">Reqid</span><span class="p">:</span><span class="w"> </span><span class="n">JCYAAB2A</span><span class="o">-</span><span class="n">KCu3JEV</span>
<span class="w"> </span><span class="n">Cache</span><span class="o">-</span><span class="n">Control</span><span class="p">:</span><span class="w"> </span><span class="nb">max</span><span class="o">-</span><span class="n">age</span><span class="o">=</span><span class="mi">2592000</span>
<span class="w"> </span><span class="n">ETag</span><span class="p">:</span><span class="w"> </span><span class="n">W</span><span class="o">/</span><span class="s2">"FupX-eSMnVrkAsAr7E6aNcS8eye6"</span>
<span class="w"> </span><span class="n">X</span><span class="o">-</span><span class="n">Log</span><span class="p">:</span><span class="w"> </span><span class="n">redis</span><span class="o">.</span><span class="n">g</span><span class="o">/</span><span class="mi">404</span><span class="p">;</span><span class="n">rdb</span><span class="o">.</span><span class="n">g</span><span class="o">/</span><span class="n">no</span><span class="w"> </span><span class="n">such</span><span class="w"> </span><span class="n">key</span><span class="p">;</span><span class="n">DBD</span><span class="o">/</span><span class="mi">404</span><span class="p">;</span><span class="n">v4</span><span class="o">.</span><span class="n">get</span><span class="o">/</span><span class="n">Document</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="n">found</span><span class="p">;</span><span class="n">rs5_shard</span><span class="o">.</span><span class="n">sel</span><span class="p">:</span><span class="mi">2</span><span class="p">;</span><span class="n">rwro</span><span class="o">.</span><span class="n">get</span><span class="p">:</span><span class="mi">3</span><span class="p">;</span><span class="n">RS</span><span class="o">.</span><span class="n">dbs</span><span class="p">:</span><span class="mi">3</span><span class="p">;</span><span class="n">RS</span><span class="p">:</span><span class="mi">3</span><span class="p">;</span><span class="n">redis</span><span class="o">.</span><span class="n">s</span><span class="p">;</span><span class="mi">2</span><span class="n">s</span><span class="o">.</span><span class="n">gh</span><span class="p">;</span><span class="n">PFDS</span><span class="p">;</span><span class="n">IO</span><span class="p">:</span><span class="mi">5</span>
<span class="w"> </span><span class="n">X</span><span class="o">-</span><span class="n">Slice</span><span class="o">-</span><span class="n">ETag</span><span class="p">:</span><span class="w"> </span><span class="n">FupX</span><span class="o">-</span><span class="n">eSMnVrkAsAr7E6aNcS8eye6</span>
<span class="w"> </span><span class="n">X</span><span class="o">-</span><span class="n">Slice</span><span class="o">-</span><span class="n">Complete</span><span class="o">-</span><span class="n">Length</span><span class="p">:</span><span class="w"> </span><span class="mi">3461591</span>
<span class="w"> </span><span class="n">X</span><span class="o">-</span><span class="n">Slice</span><span class="o">-</span><span class="n">Size</span><span class="p">:</span><span class="w"> </span><span class="mi">1048576</span>
<span class="w"> </span><span class="n">Content</span><span class="o">-</span><span class="n">Transfer</span><span class="o">-</span><span class="n">Encoding</span><span class="p">:</span><span class="w"> </span><span class="n">binary</span>
<span class="w"> </span><span class="n">X</span><span class="o">-</span><span class="n">Qnm</span><span class="o">-</span><span class="n">Cache</span><span class="p">:</span><span class="w"> </span><span class="n">Miss</span>
<span class="w"> </span><span class="n">X</span><span class="o">-</span><span class="n">Svr</span><span class="p">:</span><span class="w"> </span><span class="n">IO</span>
<span class="w"> </span><span class="n">Access</span><span class="o">-</span><span class="n">Control</span><span class="o">-</span><span class="n">Expose</span><span class="o">-</span><span class="n">Headers</span><span class="p">:</span><span class="w"> </span><span class="n">X</span><span class="o">-</span><span class="n">Log</span><span class="p">,</span><span class="w"> </span><span class="n">X</span><span class="o">-</span><span class="n">Reqid</span>
<span class="w"> </span><span class="n">Access</span><span class="o">-</span><span class="n">Control</span><span class="o">-</span><span class="n">Allow</span><span class="o">-</span><span class="n">Origin</span><span class="p">:</span><span class="w"> </span><span class="o">*</span>
<span class="w"> </span><span class="n">X</span><span class="o">-</span><span class="n">M</span><span class="o">-</span><span class="n">Reqid</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="n">mcAAMfJXKCu3JEV</span>
<span class="w"> </span><span class="n">X</span><span class="o">-</span><span class="n">Qiniu</span><span class="o">-</span><span class="n">Zone</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span>
<span class="w"> </span><span class="n">X</span><span class="o">-</span><span class="n">M</span><span class="o">-</span><span class="n">Log</span><span class="p">:</span><span class="w"> </span><span class="n">QNM</span><span class="p">:</span><span class="n">xs1163</span><span class="p">;</span><span class="n">SRCPROXY</span><span class="p">:</span><span class="n">xs485</span><span class="p">;</span><span class="n">SRC</span><span class="p">:</span><span class="mi">31</span><span class="p">;</span><span class="n">SRCPROXY</span><span class="p">:</span><span class="mi">31</span><span class="p">;</span><span class="n">QNM3</span><span class="p">:</span><span class="mi">138</span>
<span class="w"> </span><span class="n">Last</span><span class="o">-</span><span class="n">Modified</span><span class="p">:</span><span class="w"> </span><span class="n">Wed</span><span class="p">,</span><span class="w"> </span><span class="mi">03</span><span class="w"> </span><span class="n">Apr</span><span class="w"> </span><span class="mi">2019</span><span class="w"> </span><span class="mi">04</span><span class="p">:</span><span class="mi">31</span><span class="p">:</span><span class="mi">53</span><span class="w"> </span><span class="n">GMT</span>
<span class="w"> </span><span class="n">Access</span><span class="o">-</span><span class="n">Control</span><span class="o">-</span><span class="n">Max</span><span class="o">-</span><span class="n">Age</span><span class="p">:</span><span class="w"> </span><span class="mi">2592000</span>
<span class="w"> </span><span class="n">Expires</span><span class="p">:</span><span class="w"> </span><span class="n">Fri</span><span class="p">,</span><span class="w"> </span><span class="mi">03</span><span class="w"> </span><span class="n">May</span><span class="w"> </span><span class="mi">2019</span><span class="w"> </span><span class="mi">04</span><span class="p">:</span><span class="mi">33</span><span class="p">:</span><span class="mi">06</span><span class="w"> </span><span class="n">GMT</span>
<span class="w"> </span><span class="n">Age</span><span class="p">:</span><span class="w"> </span><span class="mi">101</span>
<span class="w"> </span><span class="n">X</span><span class="o">-</span><span class="n">Request</span><span class="o">-</span><span class="n">Id</span><span class="p">:</span><span class="w"> </span><span class="mi">67</span><span class="n">a882de6a2b534dd68e3fe0a15c7128</span><span class="p">;</span><span class="w"> </span><span class="mi">7</span><span class="n">f96de58c802da2ccd119a99b08623f6</span>
<span class="w"> </span><span class="n">Via</span><span class="p">:</span><span class="w"> </span><span class="n">S</span><span class="o">.</span><span class="n">mix</span><span class="o">-</span><span class="n">js</span><span class="o">-</span><span class="n">czx2</span><span class="o">-</span><span class="mi">045</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="o">.</span><span class="mf">46.</span><span class="n">M</span><span class="p">,</span><span class="w"> </span><span class="n">V</span><span class="o">.</span><span class="n">mix</span><span class="o">-</span><span class="n">js</span><span class="o">-</span><span class="n">czx2</span><span class="o">-</span><span class="mi">049</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="o">.</span><span class="mf">231.</span><span class="n">H</span><span class="p">,</span><span class="w"> </span><span class="n">M</span><span class="o">.</span><span class="n">cmn</span><span class="o">-</span><span class="n">gd</span><span class="o">-</span><span class="n">can</span><span class="o">-</span><span class="mi">228</span>
<span class="w"> </span><span class="n">Content</span><span class="o">-</span><span class="n">Encoding</span><span class="p">:</span><span class="w"> </span><span class="n">gzip</span>
<span class="n">Package</span><span class="w"> </span><span class="n">Control</span><span class="p">:</span><span class="w"> </span><span class="n">Caching</span><span class="w"> </span><span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="mf">101.</span><span class="n">zoomquiet</span><span class="o">.</span><span class="n">top</span><span class="o">/</span><span class="n">res</span><span class="o">/</span><span class="n">subl</span><span class="o">/</span><span class="n">channel_v3</span><span class="o">.</span><span class="n">json</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="o">/</span><span class="n">Users</span><span class="o">/</span><span class="n">zoomq</span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Application</span><span class="w"> </span><span class="n">Support</span><span class="o">/</span><span class="n">Sublime</span><span class="w"> </span><span class="n">Text</span><span class="w"> </span><span class="mi">3</span><span class="o">/</span><span class="n">Packages</span><span class="o">/</span><span class="n">User</span><span class="o">/</span><span class="n">Package</span><span class="w"> </span><span class="n">Control</span><span class="o">.</span><span class="n">cache</span><span class="o">/</span><span class="mi">5</span><span class="n">bd341de6f2ee7d8d6c4aa065520052a</span>
<span class="n">Package</span><span class="w"> </span><span class="n">Control</span><span class="p">:</span><span class="w"> </span><span class="n">Urllib</span><span class="w"> </span><span class="n">HTTP</span><span class="w"> </span><span class="n">Debug</span><span class="w"> </span><span class="n">General</span>
<span class="w"> </span><span class="n">Closing</span><span class="w"> </span><span class="n">connection</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="mf">101.</span><span class="n">zoomquiet</span><span class="o">.</span><span class="n">top</span><span class="w"> </span><span class="n">on</span><span class="w"> </span><span class="n">port</span><span class="w"> </span><span class="mi">80</span><span class="w"> </span><span class="n">after</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">request</span>
</code></pre></div>
<h2 id="sayeahooo">Sayeahooo<a class="headerlink" href="#sayeahooo" title="Permanent link">¶</a></h2>
<blockquote>
<p>所以, 有一个可以随时发布自己资源的外网空间是好的...</p>
</blockquote>
<ul>
<li>1.5h 资料搜索理解</li>
<li>2d 冷静</li>
<li>.5h 实施</li>
<li>.5h 文档嗯哼...</li>
</ul>Python 列表为毛从0开始索引?2019-03-23T00:00:00+08:002020-05-31T16:48:03+08:00Zoom.Quiettag:blog.zoomquiet.io,2019-03-23:/131023-why0base-indexing-python.html
<p><a href="https://plus.google.com/115212051037621986145/posts/YTUxbXYZyfi">I was asked on Twitter why Python uses 0-based indexing,...</a></p>
<p>老爹当年也很是积累使用 G+ 的,
公开回答了很多价值问题...
能看一眼少一眼了...</p>
<h2 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<blockquote>
<blockquote>
<blockquote>
<p>Google+ 帐号将于 2019 …</p></blockquote></blockquote></blockquote>
<p><a href="https://plus.google.com/115212051037621986145/posts/YTUxbXYZyfi">I was asked on Twitter why Python uses 0-based indexing,...</a></p>
<p>老爹当年也很是积累使用 G+ 的,
公开回答了很多价值问题...
能看一眼少一眼了...</p>
<h2 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<blockquote>
<blockquote>
<blockquote>
<p>Google+ 帐号将于 2019 年 4 月 2 日关停. 下载 Google+ 内容可能需要一些时间,因此请在 2019 年 3 月 31 日之前开始下载. </p>
</blockquote>
</blockquote>
</blockquote>
<h2 id="_2">发现<a class="headerlink" href="#_2" title="Permanent link">¶</a></h2>
<blockquote>
<p>Guido van Rossum</p>
<blockquote>
<p>公开</p>
<blockquote>
<p>2013年10月23日</p>
</blockquote>
</blockquote>
</blockquote>
<p>I was asked on Twitter why Python uses 0-based indexing, with a link to a new (fascinating) post on the subject (http://exple.tive.org/blarg/2013/10/22/citation-needed/). I recall thinking about it a lot; ABC, one of Python's predecessors, used 1-based indexing, while C, the other big influence, used 0-based. My first few programming languages (Algol, Fortran, Pascal) used 1-based or variable-based. I think that one of the issues that helped me decide was slice notation.</p>
<p>Let's first look at use cases. Probably the most common use cases for slicing are "get the first n items" and "get the next n items starting at i" (the first is a special case of that for i == the first index). It would be nice if both of these could be expressed as without awkward +1 or -1 compensations.</p>
<p>Using 0-based indexing, half-open intervals, and suitable defaults (as Python ended up having), they are beautiful: a[:n] and a[i:i+n]; the former is long for a[0:n].</p>
<p>Using 1-based indexing, if you want a[:n] to mean the first n elements, you either have to use closed intervals or you can use a slice notation that uses start and length as the slice parameters. Using half-open intervals just isn't very elegant when combined with 1-based indexing. Using closed intervals, you'd have to write a[i:i+n-1] for the n items starting at i. So perhaps using the slice length would be more elegant with 1-based indexing? Then you could write a[i:n]. And this is in fact what ABC did -- it used a different notation so you could write a@i|n.(See http://homepages.cwi.nl/~steven/abc/qr.html#EXPRESSIONS.)</p>
<p>But how does the index:length convention work out for other use cases? TBH this is where my memory gets fuzzy, but I think I was swayed by the elegance of half-open intervals. Especially the invariant that when two slices are adjacent, the first slice's end index is the second slice's start index is just too beautiful to ignore. For example, suppose you split a string into three parts at indices i and j -- the parts would be a[:i], a[i:j], and a[j:].</p>
<p>So that's why Python uses 0-based indexing.</p>
<h2 id="_3">是也乎<a class="headerlink" href="#_3" title="Permanent link">¶</a></h2>
<blockquote>
<p>简单说, 就是为了切片时的语义合理性...</p>
</blockquote>如何自在定义 macOS 截屏文件名?2019-02-13T22:42:00+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2019-02-13:/how2rename-mac-screen-shot.html
<h2 id="bg">BG<a class="headerlink" href="#bg" title="Permanent link">¶</a></h2>
<ul>
<li>默认系统截屏工具输出图片是:<ul>
<li>到桌面</li>
<li>文件名: <code>屏幕快照 2019-02-13 17.17.32.png</code></li>
</ul>
</li>
</ul>
<h2 id="goal">goal<a class="headerlink" href="#goal" title="Permanent link">¶</a></h2>
<ul>
<li>当年在 Linux 中,是可以自由定义输出的, 俺期望是:<ul>
<li><code>screenshot_190213-17 …</code></li></ul></li></ul>
<h2 id="bg">BG<a class="headerlink" href="#bg" title="Permanent link">¶</a></h2>
<ul>
<li>默认系统截屏工具输出图片是:<ul>
<li>到桌面</li>
<li>文件名: <code>屏幕快照 2019-02-13 17.17.32.png</code></li>
</ul>
</li>
</ul>
<h2 id="goal">goal<a class="headerlink" href="#goal" title="Permanent link">¶</a></h2>
<ul>
<li>当年在 Linux 中,是可以自由定义输出的, 俺期望是:<ul>
<li><code>screenshot_190213-17.17.32.jpg</code></li>
</ul>
</li>
<li>现在怎么作到?</li>
</ul>
<h2 id="logging">logging<a class="headerlink" href="#logging" title="Permanent link">¶</a></h2>
<blockquote>
<p>记要尝试过程</p>
</blockquote>
<h3 id="_1">格式<a class="headerlink" href="#_1" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>defaults<span class="w"> </span>write<span class="w"> </span>com.apple.screencapture<span class="w"> </span><span class="nb">type</span><span class="w"> </span>jpg
$<span class="w"> </span>killall<span class="w"> </span>SystemUIServer
</code></pre></div>
<p>以上即可</p>
<h3 id="_2">命名<a class="headerlink" href="#_2" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>defaults<span class="w"> </span>write<span class="w"> </span>com.apple.screencapture<span class="w"> </span>name<span class="w"> </span>screenshot
$<span class="w"> </span>killall<span class="w"> </span>SystemUIServer
</code></pre></div>
<p>以上只能变成:</p>
<div class="highlight"><pre><span></span><code>screenshot 2019-02-13 17.17.32.jpg
</code></pre></div>
<h3 id="screencapturestrings">ScreenCapture.strings<a class="headerlink" href="#screencapturestrings" title="Permanent link">¶</a></h3>
<p>以往可以进行的</p>
<div class="highlight"><pre><span></span><code>sudo su
cd /System/Library/CoreServices/SystemUIServer.app/Contents/Resources/Spanish.lpro
plutil -convert xml1 ScreenCapture.strings
vim ScreenCapture.strings
</code></pre></div>
<p>在 macOS Sierra 10.12.6 中失败:</p>
<ul>
<li>无论是否是 root 身份</li>
<li>都说系统没有权限</li>
</ul>
<h3 id="automator">Automator<a class="headerlink" href="#automator" title="Permanent link">¶</a></h3>
<p>另外一种思路是用内置自动脚本来刷指定目录中指定文件名的文件名:</p>
<ul>
<li>但是, 尝试后发现, 这种可视化编程限制太多</li>
<li>而且调整困难, 根本无法有效完成设想</li>
</ul>
<h3 id="bash">bash<a class="headerlink" href="#bash" title="Permanent link">¶</a></h3>
<p>经检测:</p>
<div class="highlight"><pre><span></span><code>screencapture -io ~/Desktop/screenshot_`date '+%y%m%d-%H.%M.%S'`.jpg
</code></pre></div>
<p>可以满足所有构想,可是:</p>
<ul>
<li>先要打开终端</li>
<li>运行, 无论是配置为别名, 还是部署为指定 .sh 脚本</li>
<li>然后才能进行截屏</li>
<li>相比原先随时 <code>cmd+shift+4</code> 进入截屏, 还是多了一层, 不方便</li>
</ul>
<p>问题变成如何可以用原有快捷键调用 bash 指令?</p>
<ul>
<li>alfred 复杂</li>
<li>HotKey 只能绑定 .app 使用自定快捷键<ul>
<li>那么问题进一步变成: <code>如何快速将一个 shell 脚本变成标准 mac app?</code></li>
<li>果然有很多方式, 脚本,编译,应用...</li>
<li>试用 Platypus 一下子就形成了无界面后台运行的 app</li>
</ul>
</li>
<li>配合 HotKay 达成目标效果 ;-)</li>
</ul>
<p><img alt="screenshot_190213" src="https://ipic.zoomquiet.top/2019-02-13-screenshot_190213-23.03.43.jpg"/></p>
<h2 id="refer">refer<a class="headerlink" href="#refer" title="Permanent link">¶</a></h2>
<ul>
<li><a href="http://snowleopardtips.net/tips/everything-you-need-to-know-about-screen-captures.html">TIP: Change default screen shot filenames, format and location | Snow Leopard Tips</a><ul>
<li><a href="https://www.tekrevue.com/tip/how-to-customize-screenshot-options-in-mac-os-x/">The Complete Guide to Mac OS X Screenshots - TekRevue</a></li>
<li><a href="https://apple.stackexchange.com/questions/27729/changing-the-default-screenshot-filename">uti - Changing the default screenshot filename - Ask Different</a></li>
<li>...</li>
</ul>
</li>
<li><a href="https://apple.stackexchange.com/questions/200125/how-to-create-an-osx-application-to-wrap-a-call-to-a-shell-script">macos - How to create an OSX Application to wrap a call to a shell script? - Ask Different</a><ul>
<li><a href="https://apple.stackexchange.com/questions/103621/run-applescript-from-bash-script">macos - Run AppleScript from bash script - Ask Different</a></li>
<li><a href="https://stackoverflow.com/questions/30792569/converting-a-shell-script-into-a-app-file">macos - Converting a Shell Script Into a *.app File - Stack Overflow</a></li>
<li><a href="https://christopher.su/2012/creating-mac-applications-shell-scripts/">Creating Mac Applications from Shell Scripts - Christopher Su</a></li>
<li><a href="https://sveinbjorn.org/platypus">Platypus - Create Mac apps from command line scripts |</a></li>
</ul>
</li>
</ul>
<h2 id="sayeahooo">Sayeahooo<a class="headerlink" href="#sayeahooo" title="Permanent link">¶</a></h2>
<ul>
<li>1.5h 资料搜索理解</li>
<li>2h 嗯哼</li>
<li>.5h 截屏,文档嗯哼...</li>
</ul>如何持证 (SSL) 开车2019-01-30T10:10:00+08:002019-08-19T17:30:30+08:00Zoom.Quiettag:blog.zoomquiet.io,2019-01-30:/jump-into-ssl.html
<h2 id="bg">BG<a class="headerlink" href="#bg" title="Permanent link">¶</a></h2>
<p><a href="https://mp.weixin.qq.com/s/qig7l-Tc1P6gp_Ldm2bQJg">Let's Encrypt 2019:带来更多振奋人心的新功能 - 开源中国</a></p>
<p>被成功安利...</p>
<h2 id="goal">goal<a class="headerlink" href="#goal" title="Permanent link">¶</a></h2>
<p>因各种网站发布的年代, 使用技术各不相同, 但是好在都能 …</p>
<h2 id="bg">BG<a class="headerlink" href="#bg" title="Permanent link">¶</a></h2>
<p><a href="https://mp.weixin.qq.com/s/qig7l-Tc1P6gp_Ldm2bQJg">Let's Encrypt 2019:带来更多振奋人心的新功能 - 开源中国</a></p>
<p>被成功安利...</p>
<h2 id="goal">goal<a class="headerlink" href="#goal" title="Permanent link">¶</a></h2>
<p>因各种网站发布的年代, 使用技术各不相同, 但是好在都能依托 <code>*-pages</code> 服务快速发布:</p>
<ul>
<li>github/gitlab 为核心</li>
<li>免费 SSL 认证为基础</li>
<li>最好能一次配置长期可用</li>
</ul>
<h2 id="logging">logging<a class="headerlink" href="#logging" title="Permanent link">¶</a></h2>
<p>整体上, 无论在哪个 <code>*-pages</code> 平台, 要折腾的事儿相似, 就3步:</p>
<ul>
<li>追加配置含 <code>SSL</code> 解析能力的 DNS 服务主机 <code>A</code> 地址<ul>
<li>并解决引发的有关 <code>CANEM</code> 冲突问题</li>
</ul>
</li>
<li>在 <code>*-pages</code> 平台配置 <code>Enforce HTTPS</code> 有关嗯哼</li>
<li>优雅的等待一切生效 ;-)<ul>
<li>并解决可能的资源冲突问题</li>
</ul>
</li>
</ul>
<h3 id="gh-pages">gh-pages<a class="headerlink" href="#gh-pages" title="Permanent link">¶</a></h3>
<p>原先的:</p>
<blockquote>
<p>༄ dig blog.zoomquiet.io +nostats +nocomments +nocmd</p>
</blockquote>
<div class="highlight"><pre><span></span><code><span class="o">;</span><span class="w"> </span><span class="o"><<>></span><span class="w"> </span><span class="nt">DiG</span><span class="w"> </span><span class="nt">9</span><span class="p">.</span><span class="nc">8</span><span class="p">.</span><span class="nc">3-P1</span><span class="w"> </span><span class="o"><<>></span><span class="w"> </span><span class="nt">blog</span><span class="p">.</span><span class="nc">zoomquiet</span><span class="p">.</span><span class="nc">io</span><span class="w"> </span><span class="o">+</span><span class="nt">nostats</span><span class="w"> </span><span class="o">+</span><span class="nt">nocomments</span><span class="w"> </span><span class="o">+</span><span class="nt">nocmd</span>
<span class="o">;;</span><span class="w"> </span><span class="nt">global</span><span class="w"> </span><span class="nt">options</span><span class="o">:</span><span class="w"> </span><span class="o">+</span><span class="nt">cmd</span>
<span class="o">;</span><span class="nt">blog</span><span class="p">.</span><span class="nc">zoomquiet</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span>
<span class="nt">blog</span><span class="p">.</span><span class="nc">zoomquiet</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">600</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">CNAME</span><span class="w"> </span><span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">github</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span>
<span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">github</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">3251</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span><span class="w"> </span><span class="nt">185</span><span class="p">.</span><span class="nc">199</span><span class="p">.</span><span class="nc">108</span><span class="p">.</span><span class="nc">153</span>
<span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">github</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">3251</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span><span class="w"> </span><span class="nt">185</span><span class="p">.</span><span class="nc">199</span><span class="p">.</span><span class="nc">109</span><span class="p">.</span><span class="nc">153</span>
<span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">github</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">3251</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span><span class="w"> </span><span class="nt">185</span><span class="p">.</span><span class="nc">199</span><span class="p">.</span><span class="nc">110</span><span class="p">.</span><span class="nc">153</span>
<span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">github</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">3251</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span><span class="w"> </span><span class="nt">185</span><span class="p">.</span><span class="nc">199</span><span class="p">.</span><span class="nc">111</span><span class="p">.</span><span class="nc">153</span>
</code></pre></div>
<ul>
<li>暂停原先 <code>CNAME</code> -> <code>ZoomQuiet.github.io.</code></li>
<li>追加新 <code>A</code> 记录-><code>185.199.111.153</code></li>
<li>立即...</li>
</ul>
<blockquote>
<p>༄ dig blog.zoomquiet.io +nostats +nocomments +nocmd</p>
</blockquote>
<div class="highlight"><pre><span></span><code><span class="o">;</span><span class="w"> </span><span class="o"><<>></span><span class="w"> </span><span class="nt">DiG</span><span class="w"> </span><span class="nt">9</span><span class="p">.</span><span class="nc">8</span><span class="p">.</span><span class="nc">3-P1</span><span class="w"> </span><span class="o"><<>></span><span class="w"> </span><span class="nt">blog</span><span class="p">.</span><span class="nc">zoomquiet</span><span class="p">.</span><span class="nc">io</span><span class="w"> </span><span class="o">+</span><span class="nt">nostats</span><span class="w"> </span><span class="o">+</span><span class="nt">nocomments</span><span class="w"> </span><span class="o">+</span><span class="nt">nocmd</span>
<span class="o">;;</span><span class="w"> </span><span class="nt">global</span><span class="w"> </span><span class="nt">options</span><span class="o">:</span><span class="w"> </span><span class="o">+</span><span class="nt">cmd</span>
<span class="o">;</span><span class="nt">blog</span><span class="p">.</span><span class="nc">zoomquiet</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span>
<span class="nt">blog</span><span class="p">.</span><span class="nc">zoomquiet</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">600</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">CNAME</span><span class="w"> </span><span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">github</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span>
<span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">github</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">2989</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span><span class="w"> </span><span class="nt">185</span><span class="p">.</span><span class="nc">199</span><span class="p">.</span><span class="nc">111</span><span class="p">.</span><span class="nc">153</span>
<span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">github</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">2989</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span><span class="w"> </span><span class="nt">185</span><span class="p">.</span><span class="nc">199</span><span class="p">.</span><span class="nc">108</span><span class="p">.</span><span class="nc">153</span>
<span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">github</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">2989</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span><span class="w"> </span><span class="nt">185</span><span class="p">.</span><span class="nc">199</span><span class="p">.</span><span class="nc">109</span><span class="p">.</span><span class="nc">153</span>
<span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">github</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">2989</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span><span class="w"> </span><span class="nt">185</span><span class="p">.</span><span class="nc">199</span><span class="p">.</span><span class="nc">110</span><span class="p">.</span><span class="nc">153</span>
</code></pre></div>
<p>触发对应 gh-pages 配置处 <code>CNAME</code> 冲突报警</p>
<p><img alt="冲突报警" src="_images/ssl-gh-pages-alert-cname.png"/></p>
<p>删除原先 <code>blog.zoomquiet.io</code> 定制域名后, gh-pages 状态恢复:</p>
<p><img alt="暂时默认" src="_images/ssl-gh-pages-revert-domain.png"/></p>
<ul>
<li>然而, 这肯定不是俺要的效果哪...</li>
<li>进一步的, 发现, 这是 <code>DNSPod</code> 的问题</li>
<li>namecheap 等等, 其它老厂, 是支持这种 <code>A</code> 记录和 <code>CNAME</code> 记录指向不同的</li>
<li>
<p>所以, 回查当初域名服务商:</p>
<ul>
<li>才发现, 因为抢注的早, 当年支付私人购买 <code>.io</code> 的 iwantmyname.com</li>
<li>实在太弱, 根本没有完备的域名配置服务</li>
<li>而且一直以来域名托管年费也比其它大厂贵一倍</li>
<li>说不得, 只能迁移了:</li>
</ul>
</li>
<li>
<p>先 <code>unlock</code></p>
</li>
<li>获得 <code>Transfer Auth Code</code></li>
<li>再到 namecheap 发起转移工单</li>
<li>再回 iwantmyname 同意转移</li>
<li>等待生效</li>
<li>再将 DNSPod 上对应各种配置, 逐一手工配置回 namecheap 中</li>
<li>再对应增补 SSL 依赖的 gh-pages 有关配置:<ul>
<li>blog 主机 <code>A</code> 记录-><code>185.199.111.153</code></li>
<li>blog 主机 <code>CNAME</code> -> <code>ZoomQuiet.github.io.</code></li>
</ul>
</li>
</ul>
<p>迁移前:</p>
<blockquote>
<p>༄ dig zoomquiet.io +nostats +nocomments +nocmd</p>
</blockquote>
<div class="highlight"><pre><span></span><code><span class="o">;</span><span class="w"> </span><span class="o"><<>></span><span class="w"> </span><span class="nt">DiG</span><span class="w"> </span><span class="nt">9</span><span class="p">.</span><span class="nc">8</span><span class="p">.</span><span class="nc">3-P1</span><span class="w"> </span><span class="o"><<>></span><span class="w"> </span><span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">io</span><span class="w"> </span><span class="o">+</span><span class="nt">nostats</span><span class="w"> </span><span class="o">+</span><span class="nt">nocomments</span><span class="w"> </span><span class="o">+</span><span class="nt">nocmd</span>
<span class="o">;;</span><span class="w"> </span><span class="nt">global</span><span class="w"> </span><span class="nt">options</span><span class="o">:</span><span class="w"> </span><span class="o">+</span><span class="nt">cmd</span>
<span class="o">;</span><span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span>
<span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">600</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span><span class="w"> </span><span class="nt">172</span><span class="p">.</span><span class="nc">105</span><span class="p">.</span><span class="nc">199</span><span class="p">.</span><span class="nc">192</span>
<span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">600</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">NS</span><span class="w"> </span><span class="nt">f1g1ns1</span><span class="p">.</span><span class="nc">dnspod</span><span class="p">.</span><span class="nc">net</span><span class="o">.</span>
<span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">600</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">NS</span><span class="w"> </span><span class="nt">f1g1ns2</span><span class="p">.</span><span class="nc">dnspod</span><span class="p">.</span><span class="nc">net</span><span class="o">.</span>
<span class="o">...</span>
</code></pre></div>
<blockquote>
<p>先给銭:</p>
</blockquote>
<p><img alt="迁移费用" src="_images/ssl-domain-transfer-pay.png"/></p>
<blockquote>
<p>再同意...</p>
</blockquote>
<p><img alt="同意迁移" src="_images/ssl-domain-transfer.png"/></p>
<ul>
<li>而且人家立即有挽救邮件来问, 为毛走哪....</li>
</ul>
<p><img alt="邮件事务" src="_images/ssl-domain-transfer-flow.png"/></p>
<blockquote>
<p>namecheap 中进行恢复</p>
</blockquote>
<p><img alt="旧解析" src="_images/ssl-domain-dnspod.png"/></p>
<blockquote>
<p>使用官方模板, 替代 <code>DNSPod</code> 代理的...</p>
</blockquote>
<p><img alt="解析模板" src="_images/ssl-domain-dns2namecheap.png"/></p>
<p><img alt="生效等待" src="_images/ssl-domain-waitting.png"/></p>
<p><img alt="迁移成功" src="_images/ssl-domain-in-namecheap.png"/></p>
<p>迁移并重置后:</p>
<blockquote>
<p>༄ dig zoomquiet.io +nostats +nocomments +nocmd</p>
</blockquote>
<div class="highlight"><pre><span></span><code><span class="o">;</span><span class="w"> </span><span class="o"><<>></span><span class="w"> </span><span class="nt">DiG</span><span class="w"> </span><span class="nt">9</span><span class="p">.</span><span class="nc">8</span><span class="p">.</span><span class="nc">3-P1</span><span class="w"> </span><span class="o"><<>></span><span class="w"> </span><span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">io</span><span class="w"> </span><span class="o">+</span><span class="nt">nostats</span><span class="w"> </span><span class="o">+</span><span class="nt">nocomments</span><span class="w"> </span><span class="o">+</span><span class="nt">nocmd</span>
<span class="o">;;</span><span class="w"> </span><span class="nt">global</span><span class="w"> </span><span class="nt">options</span><span class="o">:</span><span class="w"> </span><span class="o">+</span><span class="nt">cmd</span>
<span class="o">;</span><span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span>
<span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">600</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span><span class="w"> </span><span class="nt">172</span><span class="p">.</span><span class="nc">105</span><span class="p">.</span><span class="nc">199</span><span class="p">.</span><span class="nc">192</span>
</code></pre></div>
<ul>
<li>然后, 逐一先将老的 几十条配置, 逐一复制到 namecheap 解析面板中</li>
<li>然后, 按照文档要求的,配置好:</li>
</ul>
<p><img alt="全部OK" src="_images/ssl-domain-ko.png"/></p>
<blockquote>
<p>༄ dig blog.zoomquiet.io +nostats +nocomments +nocmd</p>
</blockquote>
<div class="highlight"><pre><span></span><code><span class="o">;</span><span class="w"> </span><span class="o"><<>></span><span class="w"> </span><span class="nt">DiG</span><span class="w"> </span><span class="nt">9</span><span class="p">.</span><span class="nc">8</span><span class="p">.</span><span class="nc">3-P1</span><span class="w"> </span><span class="o"><<>></span><span class="w"> </span><span class="nt">blog</span><span class="p">.</span><span class="nc">zoomquiet</span><span class="p">.</span><span class="nc">io</span><span class="w"> </span><span class="o">+</span><span class="nt">nostats</span><span class="w"> </span><span class="o">+</span><span class="nt">nocomments</span><span class="w"> </span><span class="o">+</span><span class="nt">nocmd</span>
<span class="o">;;</span><span class="w"> </span><span class="nt">global</span><span class="w"> </span><span class="nt">options</span><span class="o">:</span><span class="w"> </span><span class="o">+</span><span class="nt">cmd</span>
<span class="o">;</span><span class="nt">blog</span><span class="p">.</span><span class="nc">zoomquiet</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span>
<span class="nt">blog</span><span class="p">.</span><span class="nc">zoomquiet</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">1799</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">CNAME</span><span class="w"> </span><span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">github</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span>
<span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">github</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">3600</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span><span class="w"> </span><span class="nt">185</span><span class="p">.</span><span class="nc">199</span><span class="p">.</span><span class="nc">111</span><span class="p">.</span><span class="nc">153</span>
<span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">github</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">3600</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span><span class="w"> </span><span class="nt">185</span><span class="p">.</span><span class="nc">199</span><span class="p">.</span><span class="nc">110</span><span class="p">.</span><span class="nc">153</span>
<span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">github</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">3600</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span><span class="w"> </span><span class="nt">185</span><span class="p">.</span><span class="nc">199</span><span class="p">.</span><span class="nc">109</span><span class="p">.</span><span class="nc">153</span>
<span class="nt">zoomquiet</span><span class="p">.</span><span class="nc">github</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">3600</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span><span class="w"> </span><span class="nt">185</span><span class="p">.</span><span class="nc">199</span><span class="p">.</span><span class="nc">108</span><span class="p">.</span><span class="nc">153</span>
<span class="nt">github</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">698</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">NS</span><span class="w"> </span><span class="nt">ns-1622</span><span class="p">.</span><span class="nc">awsdns-10</span><span class="p">.</span><span class="nc">co</span><span class="p">.</span><span class="nc">uk</span><span class="o">.</span>
<span class="nt">github</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">698</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">NS</span><span class="w"> </span><span class="nt">ns-393</span><span class="p">.</span><span class="nc">awsdns-49</span><span class="p">.</span><span class="nc">com</span><span class="o">.</span>
<span class="nt">github</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">698</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">NS</span><span class="w"> </span><span class="nt">ns-692</span><span class="p">.</span><span class="nc">awsdns-22</span><span class="p">.</span><span class="nc">net</span><span class="o">.</span>
<span class="o">...</span>
</code></pre></div>
<blockquote>
<p>可以看到, 壕 github 全部用 AWS 域名服务来解析的...</p>
</blockquote>
<p><img alt="gh 正常" src="_images/ssl-gh-pages-ko.png"/></p>
<blockquote>
<p>此时 gi-pages 配置已经感知到一切良好</p>
</blockquote>
<p><img alt="证书有效" src="_images/ssl-chrome-info.png"/></p>
<p>点击 chrom 域名前的小图标, 可以看到 SSL 已生效</p>
<p><img alt="检验" src="_images/ssl-chrome-chk.png"/></p>
<p>当然, 原先模板中一系列资源指向老 <code>http</code> 资源都无法使用了</p>
<p><img alt="资源丢失" src="_images/ssl-res-load-err.png"/></p>
<p>修订配置文件 <code>pelicanconf.py</code>: </p>
<div class="highlight"><pre><span></span><code><span class="n">SITEURL</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">'http://blog.zoomquiet.io'</span>
<span class="o">--></span>
<span class="w"> </span><span class="s">'https://blog.zoomquiet.io'</span>
</code></pre></div>
<p>但是, 进行 push 失败:</p>
<div class="highlight"><pre><span></span><code><span class="err">༄</span><span class="w"> </span><span class="n">git</span><span class="w"> </span><span class="n">pu</span>
<span class="k">To</span><span class="w"> </span><span class="n">github</span><span class="p">.</span><span class="nl">com</span><span class="p">:</span><span class="n">ZoomQuiet</span><span class="o">/</span><span class="n">ZoomQuiet</span><span class="p">.</span><span class="n">github</span><span class="p">.</span><span class="n">io</span><span class="p">.</span><span class="n">git</span>
<span class="w"> </span><span class="err">!</span><span class="w"> </span><span class="o">[</span><span class="n">rejected</span><span class="o">]</span><span class="w"> </span><span class="n">master</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="n">master</span><span class="w"> </span><span class="p">(</span><span class="k">fetch</span><span class="w"> </span><span class="k">first</span><span class="p">)</span>
<span class="nl">error</span><span class="p">:</span><span class="w"> </span><span class="n">failed</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="n">push</span><span class="w"> </span><span class="ow">some</span><span class="w"> </span><span class="n">refs</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="s1">'git@github.com:ZoomQuiet/ZoomQuiet.github.io.git'</span>
<span class="nl">hint</span><span class="p">:</span><span class="w"> </span><span class="n">Updates</span><span class="w"> </span><span class="n">were</span><span class="w"> </span><span class="n">rejected</span><span class="w"> </span><span class="n">because</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">remote</span><span class="w"> </span><span class="k">contains</span><span class="w"> </span><span class="k">work</span><span class="w"> </span><span class="n">that</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">do</span>
<span class="nl">hint</span><span class="p">:</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="n">have</span><span class="w"> </span><span class="n">locally</span><span class="p">.</span><span class="w"> </span><span class="n">This</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">usually</span><span class="w"> </span><span class="n">caused</span><span class="w"> </span><span class="k">by</span><span class="w"> </span><span class="n">another</span><span class="w"> </span><span class="n">repository</span><span class="w"> </span><span class="n">pushing</span>
<span class="nl">hint</span><span class="p">:</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">same</span><span class="w"> </span><span class="k">ref</span><span class="p">.</span><span class="w"> </span><span class="n">You</span><span class="w"> </span><span class="n">may</span><span class="w"> </span><span class="n">want</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="k">first</span><span class="w"> </span><span class="n">integrate</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">remote</span><span class="w"> </span><span class="n">changes</span>
<span class="nl">hint</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">g</span><span class="p">.,</span><span class="w"> </span><span class="s1">'git pull ...'</span><span class="p">)</span><span class="w"> </span><span class="k">before</span><span class="w"> </span><span class="n">pushing</span><span class="w"> </span><span class="n">again</span><span class="p">.</span>
<span class="nl">hint</span><span class="p">:</span><span class="w"> </span><span class="n">See</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="s1">'Note about fast-forwards'</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="s1">'git push --help'</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">details</span><span class="p">.</span>
</code></pre></div>
<blockquote>
<p>因为仓库目录中 <code>CNAME</code> 文件自动构建过,和本地没同步上</p>
</blockquote>
<p><img alt="CNAME 重建" src="_images/ssl-domain-cname-renew.png"/></p>
<blockquote>
<p>再重新编译->push->等待 gh-pages 完成发布</p>
</blockquote>
<p><img alt="等待部署" src="_images/gh-pages-waitting.png"/></p>
<p>那个褐色小点, 变成绿色对勾, 就说明一切安好...</p>
<p><img alt="WOLA" src="_images/ssl-all-ok.png"/></p>
<h3 id="gl-pages">gl-pages<a class="headerlink" href="#gl-pages" title="Permanent link">¶</a></h3>
<p>其实, gitlab 上网站先持证上岗的...</p>
<p>先出示一下成果:</p>
<blockquote>
<p>༄ dig 101.camp +nostats +nocomments +nocmd</p>
</blockquote>
<div class="highlight"><pre><span></span><code><span class="o">;</span><span class="w"> </span><span class="o"><<>></span><span class="w"> </span><span class="nt">DiG</span><span class="w"> </span><span class="nt">9</span><span class="p">.</span><span class="nc">8</span><span class="p">.</span><span class="nc">3-P1</span><span class="w"> </span><span class="o"><<>></span><span class="w"> </span><span class="nt">101</span><span class="p">.</span><span class="nc">camp</span><span class="w"> </span><span class="o">+</span><span class="nt">nostats</span><span class="w"> </span><span class="o">+</span><span class="nt">nocomments</span><span class="w"> </span><span class="o">+</span><span class="nt">nocmd</span>
<span class="o">;;</span><span class="w"> </span><span class="nt">global</span><span class="w"> </span><span class="nt">options</span><span class="o">:</span><span class="w"> </span><span class="o">+</span><span class="nt">cmd</span>
<span class="o">;</span><span class="nt">101</span><span class="p">.</span><span class="nc">camp</span><span class="o">.</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span>
<span class="nt">101</span><span class="p">.</span><span class="nc">camp</span><span class="o">.</span><span class="w"> </span><span class="nt">1799</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">CNAME</span><span class="w"> </span><span class="nt">pythonicamp</span><span class="p">.</span><span class="nc">gitlab</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span>
<span class="nt">pythonicamp</span><span class="p">.</span><span class="nc">gitlab</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">300</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">A</span><span class="w"> </span><span class="nt">35</span><span class="p">.</span><span class="nc">185</span><span class="p">.</span><span class="nc">44</span><span class="p">.</span><span class="nc">232</span>
<span class="nt">gitlab</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">48445</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">NS</span><span class="w"> </span><span class="nt">ns-1116</span><span class="p">.</span><span class="nc">awsdns-11</span><span class="p">.</span><span class="nc">org</span><span class="o">.</span>
<span class="nt">gitlab</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">48445</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">NS</span><span class="w"> </span><span class="nt">ns-926</span><span class="p">.</span><span class="nc">awsdns-51</span><span class="p">.</span><span class="nc">net</span><span class="o">.</span>
<span class="nt">gitlab</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">48445</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">NS</span><span class="w"> </span><span class="nt">ns-1697</span><span class="p">.</span><span class="nc">awsdns-20</span><span class="p">.</span><span class="nc">co</span><span class="p">.</span><span class="nc">uk</span><span class="o">.</span>
<span class="nt">gitlab</span><span class="p">.</span><span class="nc">io</span><span class="o">.</span><span class="w"> </span><span class="nt">48445</span><span class="w"> </span><span class="nt">IN</span><span class="w"> </span><span class="nt">NS</span><span class="w"> </span><span class="nt">ns-288</span><span class="p">.</span><span class="nc">awsdns-36</span><span class="p">.</span><span class="nc">com</span><span class="o">.</span>
<span class="o">...</span>
</code></pre></div>
<h4 id="domain">domain<a class="headerlink" href="#domain" title="Permanent link">¶</a></h4>
<blockquote>
<p>首先操作就撞到神奇形象</p>
</blockquote>
<p><img alt="DNSPod 升级?" src="_images/SSL-dnspod-acord-error.png"/></p>
<p><img alt="DNSPod 冲突" src="_images/SSL-dnspod-cname-error.png"/></p>
<blockquote>
<p>不得以, 迁移回 neamcheap 来配置, 顺畅完成:</p>
</blockquote>
<p><img alt="neamcheap 可配" src="_images/SSL-namecheap-acords.png"/></p>
<ul>
<li>当然, 这波配置, 看错文档, 配置成 github 解析主机了</li>
<li>但是, 证明 DNSPod 完全不可用了...</li>
</ul>
<h4 id="pages">pages<a class="headerlink" href="#pages" title="Permanent link">¶</a></h4>
<blockquote>
<p>配置证书前, 得先生成, gitlab 不象 github 为用户自动生成, 得自行嗯哼</p>
</blockquote>
<ul>
<li>先安装 <a href="https://certbot.eff.org/">Certbot</a></li>
<li><a href="https://letsencrypt.org/">Let's Encrypt</a> 官方推出的证书生成工具</li>
</ul>
<blockquote>
<p>brew install certbot</p>
</blockquote>
<p>然后手工给对应域名生成密匙对:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>sudo<span class="w"> </span>certbot<span class="w"> </span>certonly<span class="w"> </span>-a<span class="w"> </span>manual<span class="w"> </span>-d<span class="w"> </span><span class="m">101</span>.camp<span class="w"> </span>--email<span class="w"> </span>zoom.quiet@gmail.com
</code></pre></div>
<ul>
<li>注意, 这里 <code>-d</code> 参数可以叠加</li>
<li>不过, 毎生成一个, 必须同时完成自证检验,才能继续</li>
<li>否则, 等于放弃当前生成的密匙</li>
</ul>
<blockquote>
<p>即, 蔱根据提示完成:</p>
</blockquote>
<hr/>
<div class="highlight"><pre><span></span><code>Create a file containing just this data:
iIpSoAbePD ... 1tTDSskcHQFs
And make it available on your web server at this URL:
http://101.camp/.well-known/acme-challenge/iIpSoAbePDhDmGwPUDfER-Czl_bxduu2Cp6qE-IxjLI
<span class="k">-</span> - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue
</code></pre></div>
<p>此时, 千万别按回车:</p>
<ul>
<li>得回到仓库中</li>
<li>构建 <code>.well-known/acme-challenge/iIpSoAbePDhDmGwPUDfER-Czl_bxduu2Cp6qE-IxjLI</code> 目录</li>
<li>并在其中构建 <code>index.html</code> 文件</li>
<li>文件内容就那一行提供的用来检验的数据</li>
<li>当然, 对于 gl-pages 网站</li>
<li>只是手工建立目录和文件, 复制进入数据</li>
<li>再 <code>git push</code> 就好</li>
<li>只是, 按回车前, 一定要先<ul>
<li>访问那个 URI</li>
<li>看一眼, 是否可以获得对应数据</li>
</ul>
</li>
</ul>
<blockquote>
<p>按下回车</p>
</blockquote>
<div class="highlight"><pre><span></span><code><span class="nx">Waiting</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nx">verification</span><span class="o">...</span>
<span class="nx">Cleaning</span><span class="w"> </span><span class="nx">up</span><span class="w"> </span><span class="nx">challenges</span>
<span class="nx">IMPORTANT</span><span class="w"> </span><span class="nx">NOTES</span><span class="p">:</span>
<span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">Congratulations</span><span class="p">!</span><span class="w"> </span><span class="nx">Your</span><span class="w"> </span><span class="nx">certificate</span><span class="w"> </span><span class="k">and</span><span class="w"> </span><span class="nx">chain</span><span class="w"> </span><span class="nx">have</span><span class="w"> </span><span class="nx">been</span><span class="w"> </span><span class="nx">saved</span><span class="w"> </span><span class="nx">at</span><span class="p">:</span>
<span class="w"> </span><span class="o">/</span><span class="nx">etc</span><span class="o">/</span><span class="nx">letsencrypt</span><span class="o">/</span><span class="nx">live</span><span class="o">/</span><span class="mi">101</span><span class="p">.</span><span class="nx">camp</span><span class="o">/</span><span class="nx">fullchain</span><span class="p">.</span><span class="nx">pem</span>
<span class="w"> </span><span class="nx">Your</span><span class="w"> </span><span class="nx">key</span><span class="w"> </span><span class="nx">file</span><span class="w"> </span><span class="nx">has</span><span class="w"> </span><span class="nx">been</span><span class="w"> </span><span class="nx">saved</span><span class="w"> </span><span class="nx">at</span><span class="p">:</span>
<span class="w"> </span><span class="o">/</span><span class="nx">etc</span><span class="o">/</span><span class="nx">letsencrypt</span><span class="o">/</span><span class="nx">live</span><span class="o">/</span><span class="mi">101</span><span class="p">.</span><span class="nx">camp</span><span class="o">/</span><span class="nx">privkey</span><span class="p">.</span><span class="nx">pem</span>
<span class="w"> </span><span class="nx">Your</span><span class="w"> </span><span class="nx">cert</span><span class="w"> </span><span class="nx">will</span><span class="w"> </span><span class="nx">expire</span><span class="w"> </span><span class="nx">on</span><span class="w"> </span><span class="mi">2019</span><span class="o">-</span><span class="mi">04</span><span class="o">-</span><span class="mi">23</span><span class="p">.</span><span class="w"> </span><span class="nx">To</span><span class="w"> </span><span class="nx">obtain</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">new</span><span class="w"> </span><span class="k">or</span><span class="w"> </span><span class="nx">tweaked</span>
<span class="w"> </span><span class="nx">version</span><span class="w"> </span><span class="nx">of</span><span class="w"> </span><span class="nx">this</span><span class="w"> </span><span class="nx">certificate</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">future</span><span class="p">,</span><span class="w"> </span><span class="nx">simply</span><span class="w"> </span><span class="nx">run</span><span class="w"> </span><span class="nx">certbot</span>
<span class="w"> </span><span class="nx">again</span><span class="p">.</span><span class="w"> </span><span class="nx">To</span><span class="w"> </span><span class="nx">non</span><span class="o">-</span><span class="nx">interactively</span><span class="w"> </span><span class="nx">renew</span><span class="w"> </span><span class="o">*</span><span class="nx">all</span><span class="o">*</span><span class="w"> </span><span class="nx">of</span><span class="w"> </span><span class="nx">your</span><span class="w"> </span><span class="nx">certificates</span><span class="p">,</span><span class="w"> </span><span class="nx">run</span>
<span class="w"> </span><span class="s">"certbot renew"</span>
<span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">If</span><span class="w"> </span><span class="nx">you</span><span class="w"> </span><span class="k">like</span><span class="w"> </span><span class="nx">Certbot</span><span class="p">,</span><span class="w"> </span><span class="nx">please</span><span class="w"> </span><span class="nx">consider</span><span class="w"> </span><span class="nx">supporting</span><span class="w"> </span><span class="nx">our</span><span class="w"> </span><span class="nx">work</span><span class="w"> </span><span class="nx">by</span><span class="p">:</span>
<span class="w"> </span><span class="nx">Donating</span><span class="w"> </span><span class="nx">to</span><span class="w"> </span><span class="nx">ISRG</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">Let</span><span class="err">'</span><span class="nx">s</span><span class="w"> </span><span class="nx">Encrypt</span><span class="p">:</span><span class="w"> </span><span class="nx">https</span><span class="p">:</span><span class="c1">//letsencrypt.org/donate</span>
<span class="w"> </span><span class="nx">Donating</span><span class="w"> </span><span class="nx">to</span><span class="w"> </span><span class="nx">EFF</span><span class="p">:</span><span class="w"> </span><span class="nx">https</span><span class="p">:</span><span class="c1">//eff.org/donate-le</span>
</code></pre></div>
<p>嗯哼, 好了, 出现以上类似信息</p>
<ul>
<li>说明, 已经在官方注册好并检验通过私人证书了</li>
<li>不过, 这种证书只有 4个月 寿命</li>
<li>到时得运行 <code>certbot renew</code> 一下</li>
</ul>
<p>接下来正常重新配置一下 gl-pages 中的域名</p>
<p><img alt="gl 强制嗯哼" src="_images/SSL-gl-pages-ssl.png"/></p>
<blockquote>
<p>打开 HTTPS 开关</p>
</blockquote>
<p><img alt="gl 域名上证" src="_images/SSL-gl-pages-redomain.png"/></p>
<blockquote>
<p>根据提示, 从本地 <code>letsencrypt</code> 证书目录中复制出有关嗯哼就好</p>
</blockquote>
<ul>
<li>当然, 别忘记重新在域名解析商, 配置新的 <code>TXT</code> 字串</li>
</ul>
<h4 id="waitting">waitting<a class="headerlink" href="#waitting" title="Permanent link">¶</a></h4>
<p>首先..</p>
<p><img alt="证件无效" src="_images/SSL-chrome-chk-CA-not.png"/></p>
<p>然后可以看到:</p>
<p><img alt="检验通过" src="_images/SSL-CAX3-ok.png"/></p>
<p>接着...</p>
<p><img alt="还未安全" src="_images/SSL-chrome-chk-CA-ok.png"/></p>
<p>最后...</p>
<p><img alt="部分安全" src="_images/SSL-chrome-chk-info.png"/></p>
<p>这是因为有的图片/css/js 资源, 还是用 hhtp 引用的, 得升级:</p>
<p><img alt="iPic" src="_images/ipic-http.png"/></p>
<p>俺采购的工具, 才发现主要图床还是 http 的</p>
<p>追查文档:</p>
<p><img alt="7牛有关页面" src="_images/SSL-7niu-cdn.png"/></p>
<blockquote>
<p>对比隔壁 ...</p>
</blockquote>
<p><img alt="UPYUN 有关页面" src="_images/SSL-upyun-https.png"/></p>
<p>嚓, 这不很明显, 只能选择后者了...</p>
<ul>
<li>当然, 又引发了欠费等等额外处置事务</li>
<li>那就是另外的故事了</li>
<li>但是, 反正可以先直接用 gl-pages 空间嘛<ul>
<li>已经 HHTPS 光辉笼罩下的资源渠道...</li>
</ul>
</li>
</ul>
<p><img alt="一切安全" src="_images/SSL-chrome-chk-good.png"/></p>
<p>终于...收功</p>
<h2 id="ipic">iPic<a class="headerlink" href="#ipic" title="Permanent link">¶</a></h2>
<blockquote>
<p>是的, mac 下 docker 工具中最接地气的了</p>
</blockquote>
<p>在和有关人士沟通后, 人工通过了俺单域名免费 SSL 的订单,
然后发现和对应 bucket 的配合是这样的:</p>
<ul>
<li>首先,在 SSL 采购界面中,点击 <code>补全</code></li>
</ul>
<p><img alt="补全" src="https://ipic.zoomquiet.top/2019-02-13-%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202019-02-13%2016.19.48.png"/></p>
<ul>
<li>然后才有域名绑定界面出现, 当然的要求先备案</li>
</ul>
<p><img alt="SSL 配置" src="https://ipic.zoomquiet.top/2019-02-13-%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202019-02-13%2016.32.44.png"/></p>
<ul>
<li>再回到对应云存储控制界面中, 再次绑定域名</li>
<li>最后,参考: <a href="https://help.upyun.com/knowledge-base/cdn-https/">如何进行 HTTPS 配置? – 又拍云-文档帮助中心</a><ul>
<li>还得 <code>服务管理 > 功能配置 > HTTPS</code>, 点击 <code>管理</code> 才能真正打开 HTTPS</li>
</ul>
</li>
</ul>
<p><img alt="管理" src="https://ipic.zoomquiet.top/2019-02-13-%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202019-02-13%2017.17.32.png"/></p>
<ul>
<li>这样就完成了隐藏的云端 SSL 密匙部署, 以及空间域名绑定过程</li>
<li>是的, 以上3张图片都是 <code>HTTPS</code> 持证资源了</li>
</ul>
<h2 id="summary">summary<a class="headerlink" href="#summary" title="Permanent link">¶</a></h2>
<ul>
<li>DNSPod 依然是感觉最舒服的 DNS 管理界面, 可惜彻底被放弃了, 能迁走就迁吧...<ul>
<li>而且功能已经落后</li>
</ul>
</li>
</ul>
<p><img alt="报警" src="_images/ssl-dnspod-err.png"/></p>
<ul>
<li>gitlab 比 github 要 hardcore 很多<ul>
<li>但是, 乐趣也更多也</li>
</ul>
</li>
<li>嫑怕嫑怕嫑怕<ul>
<li>官方文档, 总是最合理的</li>
<li>一定要安心静静读一遍, 比查找多少中文说明都好用</li>
<li>所以, 俺这篇, 也纯粹是私人 BDD, 包含一些隐坑, 不好意思提了<ul>
<li>就渴望您也撞到</li>
<li>好一起呵呵...</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="refer">refer<a class="headerlink" href="#refer" title="Permanent link">¶</a></h2>
<ul>
<li><a href="https://yixuan.li/geek/2019/01/21/howToDriveWithHTTPS/">如何持证 (HTTPS) 开车 · Yixuan</a><ul>
<li><a href="https://help.github.com/articles/troubleshooting-custom-domains/">GitHub Pages HTTPS 设置 | 查错指南</a></li>
<li><a href="https://help.github.com/articles/securing-your-github-pages-site-with-https/">如何给你的 GitHub Pages 加上 HTTPS 证书</a></li>
<li><a href="https://help.github.com/articles/using-a-custom-domain-with-github-pages/">Using a custom domain with GitHub Pages - User Documentation</a><ul>
<li><a href="https://help.github.com/articles/setting-up-a-custom-subdomain/">Setting up a custom subdomain - User Documentation</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="https://gitlab.com/help/user/project/pages/lets_encrypt_for_gitlab_pages.md">Lets encrypt for gitlab pages · Pages · Project · User · Help · GitLab</a><ul>
<li><a href="https://github.com/rolodato/gitlab-letsencrypt">rolodato/gitlab-letsencrypt: Easily generate a Let's Encrypt certificate for GitLab Pages</a></li>
<li><a href="https://gitlab.com/help/user/project/pages/getting_started_part_three.md#dns-records">Getting started part three · Pages · Project · User · Help · GitLab</a></li>
<li>...</li>
</ul>
</li>
<li><a href="https://www.namecheap.com/support/knowledgebase/article.aspx/9175/83/how-to-transfer-a-domain">How to Transfer a Domain - Domain Transfers -Namecheap</a><ul>
<li><a href="https://www.namecheap.com/support/knowledgebase/article.aspx/255/83/how-do-i-transfer-my-existing-domain-to-namecheap">How do I transfer my existing domain to Namecheap? - Domain Transfers</a></li>
<li><a href="https://www.namecheap.com/support/knowledgebase/article.aspx/9798/83/how-do-i-verify-that-my-domain-is-eligible-for-transfer">How do I verify that my domain is eligible for transfer? - Domain Transfers</a></li>
<li><a href="https://help.iwantmyname.com/customer/portal/articles/184477-how-do-i-transfer-a-domain-to-another-registrar-">iwantmyname | How do I transfer a domain to another re...</a></li>
<li><a href="https://help.iwantmyname.com/customer/portal/topics/83858-domain-transfer">iwantmyname | Domain Transfer</a></li>
<li>...</li>
</ul>
</li>
</ul>
<h2 id="sayeahooo">Sayeahooo<a class="headerlink" href="#sayeahooo" title="Permanent link">¶</a></h2>
<ul>
<li>1.5h 资料搜索理解</li>
<li>2d gitlab 尝试/生效</li>
<li>4h github 嗯哼<ul>
<li>3.5h 域名迁移尝试</li>
</ul>
</li>
<li>2h 截屏,文档嗯哼...</li>
<li>190213 2h 沟通以及尝试<ul>
<li>iPic 获得一个稳定 HTTPS 入口</li>
</ul>
</li>
</ul>用 DSL 们构筑商用系统2017-08-27T00:00:00+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2017-08-27:/dsl-atop-openresty.html
<h1 id="building-business-systems-with-dsls-for-nginx-openresty">Building Business Systems with DSLs for NGINX & OpenResty<a class="headerlink" href="#building-business-systems-with-dsls-for-nginx-openresty" title="Permanent link">¶</a></h1>
<p>~ 来自春哥的分享</p>
<h2 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<ul>
<li>5年前也听录了一次 春哥的分享:<a href="http://blog-zq-org.qiniucdn.com/pyblosxom/oss/openresty-intro-2012-03-06-01-13.html">由Lua 粘合的Nginx生态环境</a></li>
<li>然后, 神奇的引发了各种后来的然后</li>
<li>去年, 在 NGINX 大会 …</li></ul>
<h1 id="building-business-systems-with-dsls-for-nginx-openresty">Building Business Systems with DSLs for NGINX & OpenResty<a class="headerlink" href="#building-business-systems-with-dsls-for-nginx-openresty" title="Permanent link">¶</a></h1>
<p>~ 来自春哥的分享</p>
<h2 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<ul>
<li>5年前也听录了一次 春哥的分享:<a href="http://blog-zq-org.qiniucdn.com/pyblosxom/oss/openresty-intro-2012-03-06-01-13.html">由Lua 粘合的Nginx生态环境</a></li>
<li>然后, 神奇的引发了各种后来的然后</li>
<li>去年, 在 NGINX 大会上, 春哥才真正讲出了10年前设计 OpenResty 前身时内心的宏大构想</li>
<li>所以, 值得认真 review 一下:<ul>
<li>视频:<a href="https://www.youtube.com/watch?v=w2RAZLptE-U">Building Business Systems with Domain-Specific Languages for NGINX & OpenResty | Cloudflare - YouTube</a></li>
<li>文稿:<ul>
<li><a href="https://www.nginx.com/blog/building-business-systems-with-domain-specific-languages-for-nginx-openresty-part-1/">Domain-Specific Languages for NGINX & OpenResty, Part 1</a></li>
<li><a href="https://www.nginx.com/blog/building-business-systems-with-domain-specific-languages-for-nginx-openresty-part-2/">Domain-Specific Languages for NGINX & OpenResty, Part 1</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="tldr">TL;DR<a class="headerlink" href="#tldr" title="Permanent link">¶</a></h2>
<p><img alt="p0" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide0_First-image.png"/></p>
<p>nginx.conf 2016 春哥进行的是压轴分享,对于在主厅面对千人的演讲,
他表示了虚伪的不好意思.</p>
<p><img alt="p2" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide2_OpenResty.png"/></p>
<p>OpenResty 项目发起自10年前,现在已经有完备的团队专门进行维护和开发,
twitter 官方帐号是: @OpenResty</p>
<p>推荐关注</p>
<p><img alt="p4" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide4_Lua-Libraries.png"/></p>
<p>OpenResty 在 NGINX 内嵌了 LuaJIT 环境,
得以支持丰富的 Lua 库,结合 NGINX 原生的非阻塞机制,
支持我们可以快速的完成复杂的 web 应用系统,
当前 <code>lus-resty-*</code> 库已经支持非常多领域功能,比如说:</p>
<ul>
<li>各种数据库客户端: MySQL/Pg/MongoDB/RabbitMQ/..</li>
<li>各种 upstreams 的健康检验</li>
</ul>
<p>是的, OpenResty 是成长非常迅猛的社区</p>
<p><img alt="p5" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide5_NGINX-LuaJIT.png"/></p>
<p>OpenResty 不仅仅将 LuaJIT 嵌入到 NGINX ,
感谢 Lus 的 <code>co-routines</code> 特性,
我们还创造了独有的特性,比如说:</p>
<ul>
<li>light threads</li>
<li>timers</li>
</ul>
<h3 id="or">OR 的世界观<a class="headerlink" href="#or" title="Permanent link">¶</a></h3>
<p><img alt="p6" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide6_The-All-Inclusive-Philosophy.png"/></p>
<p>OpenResty 的世界观是 <code>全包容</code> 的,
不排斥其它任何技术, 事实上 resty 用户来自从 JAVA 到 Go 各种技术人群.</p>
<p>NGINX 可以在后端到客户端之间作很多有趣的事儿,
所以, 在 OpenResty 帮助下, 可以很好的完成混合解决,
能和旧系统无缝衔接.</p>
<p><img alt="p7" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide7_Simple-Small-Fast-Flexible.png"/></p>
<p>OpenResty 的目标是:</p>
<ul>
<li>简洁</li>
<li>轻便</li>
<li>快速</li>
<li>灵活</li>
</ul>
<p>认真研究 Lua 后, 我们发现这真是个神奇的恩物,
不仅小而且快,更加灵活,支撑复杂的大型系统也没有问题.</p>
<p>总之这是个设计务实,发展良好,基础稳定的好语言,
OpenResty 将 Lua 和 NGINX 深度结合,
倍增了双方的实力.</p>
<p><img alt="p8" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide8_Synchronously-Nonblocking.png"/></p>
<p>OpenResty 的 I/O 模式是 <code>无阻塞异步</code>,
虽然 异步 在现实世界中无处不在,
但是,人类的头脑只习惯同步,
当然,俺也反感回调</p>
<p><img alt="p9" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide9_Light-Threads-Semaphores.png"/></p>
<p>所以,我们设计了 纤程和信号 来模拟并发,
而实际上只有一个唯一的系统线程.</p>
<p><img alt="p10" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide10_Cosockets.png"/></p>
<p>并发明了: 'Cosockets' ~ 肯接字 (哈N 年前就想翻译了, 现在才有好想法儿)</p>
<p>类似 BSD/Lua 套接字的容器,
支持我们象写 PHP 代码一样写同步表述, 但实际运行是完全异步的.</p>
<p>(<code>是也乎:</code></p>
<p>golang 其实也借鉴了我们这一设计
)</p>
<p><img alt="p11" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide11_Timers-and-Sleeping.png"/></p>
<p>我们也重新定义了 计时器和睡眠原语,
将异步和下游任务在 NGINX 中完备的分离了,
使用起来就象 cron .</p>
<p><img alt="p12" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide12_Shm-Based-Dictionaries-and-Queues.png"/></p>
<p>同时还发明了 <code>shm</code> ~ 内存分享式字典和队列,
以便支持我们的应用在 NGINX 不同进程间分享数据,
同时又不打破 NGINX 的异步性能.</p>
<p><img alt="p13" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide13_Dynamic-SSL-Handshakes.png"/></p>
<p>而且刚刚我们也开始支持 动态SSL握手, 以便支持下游的 HTTPS 事务.</p>
<p><img alt="p14" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide14_Dynamic-SSL-Handshakes-Example.png"/></p>
<p>比如在 Cloudflare, 作为CDN 供应商,
有很多客户以及虚拟服务器和边缘服务器构成网络,</p>
<p>要面对的一个主要问题就是: SSL 证书/密钥太多</p>
<p>理论上应该根据实际请求来动态加载对应的证书/密钥,
这样我们就可以同时持有无限量的 SSL 证书/密钥,
感谢本地流量调度, 虽然不可能有单机可以查询所有用户的流量.</p>
<p>进一步的, 在 OpenResty 可以通过 共享内存和工作级缓存中管理 SSL 证书/密钥,</p>
<p>数据 -- 比如: 证书/密钥 -- 当前已支持在 <a href="https://github.com/alticelabs/kyoto">Kyoto Tycoon</a> 中分发,
其它后端,比如说 Redis 或其它分布式存储也当然可以了.</p>
<p><img alt="p15" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide15_Dynamic-Load-Balancers.png"/></p>
<p>通过 NGINX 中的 Lua 进行动态加载平衡也是能的.</p>
<p><img alt="p16" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide16_Dynamic-Load-Balancers-Ex.png"/></p>
<p>比如这一则配置:</p>
<ul>
<li>几行就可以定义一系列复杂的决策</li>
<li>动态, 意味着你可以在该级别上对每个请求灵活应用不同的均衡策略</li>
<li>并指定重试策略:<ul>
<li>比如, 特定请求没有获得响应时</li>
<li>可以选择忽略</li>
<li>也可以选择请求和请求的位置</li>
<li>等等,都在 <code>balancer_by_lua_block</code> 中可以声明</li>
</ul>
</li>
<li>同时不影响 NGINX 各种标准模块,比如说:<ul>
<li><a href="http://nginx.org/en/docs/http/ngx_http_proxy_module.html">Proxy</a></li>
<li><a href="http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html">FastCGI</a></li>
<li><a href="http://nginx.org/en/docs/http/ngx_http_uwsgi_module.html">uwsgi</a></li>
<li>... 等等的使用</li>
</ul>
</li>
<li>以及 NGINX 核心模块,比如: keepalive,连接池等等, 也一样开箱即用</li>
</ul>
<p><img alt="p17" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide17_ngx_stream_lua_module-TCP-UDP.png"/></p>
<p>最近我们创建了 <a href="https://github.com/openresty/stream-lua-nginx-module">ngx_stream_lua_module</a> 模块来替代以往的
<a href="https://github.com/openresty/lua-nginx-module">ngx_ HTTP_lua_ module</a></p>
<p>通过 NGINX 核心子系统,来支持实现通用的 TCP/UDP 服务,</p>
<p>实际上 <a href="http://openresty.org/en/">OpenResty® - Official Site</a>
本身的 DNS 服务器就由此模块支撑,
还有人拿个模块实现了类似 syslog 的 TCP 守护进程,
来接收远程的大量日志.</p>
<p><img alt="p18" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide18_Advanced-Debugging-Profiling-Tools-Based-on-GDB-SystemTap.png"/></p>
<p>多年以来, 我们积累了大量的专用测试工具.</p>
<p>在 Cloudflare, 运营有全球范围的复杂大型网络,
很多问题发生的几率仅仅有 1% 或 0.1% 甚至于 0.001%,
几乎难以复现, 必须依赖高级调试工具来完成.</p>
<p>已经开源了很多基于 GDB 以及 SystemTap 的工具:</p>
<ul>
<li>GDB 主要调试死锁进程,借助 GDB 以及 dump 工具, Mike Pall 已经修复了10多个隐藏在 JIT 中非常深的积年老问题</li>
<li>SystemTap 则是非常赞的 RedHat 工程师贡献的动态追踪平台,<ul>
<li>允许分享分析运行时系统, </li>
<li>从 内核到 NGINX 整个儿软件桟以及用户的 Lua 业务脚本, </li>
<li>都能在对生产系统微小影响下快速分析出来,</li>
<li>甚至于不用关闭防火墙</li>
<li>可以直接进行线上活体分析</li>
<li><-- 这才是未来系统开发的应该姿势</li>
</ul>
</li>
</ul>
<p>(<code>是也乎:</code></p>
<p>嗯哼? LISP 构造的系统, 从一开始就这样的哪?!
)</p>
<h3 id="or_1">OR 的应用场景<a class="headerlink" href="#or_1" title="Permanent link">¶</a></h3>
<p><img alt="p19" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide19_C2000K.png"/></p>
<p>随着近几个月, 我们发布的重要功能,
OpenResty 已在真实客户单主机上支持住了 200万 级别的并发请求,</p>
<p>已经有客户在生产环境中部署了这种级别的推送系统.</p>
<p><img alt="p20" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide20_Web-API-and-Microservices.png"/></p>
<p>另外一个常见领域是接口和微服务,</p>
<p>很多人使用 OpenResty 构建这类服务,比如:
<a href="https://github.com/Mashape/kong">Mashape's Kong</a>平台,
以及 <a href="https://github.com/adobe-apiplatform/apigateway">Adobe's API Gateway</a></p>
<p>此外, 一些美国银行使用 OpenResty 来管理路由器流量,</p>
<p>同时, 一些更大的中国互联网公司, 在用 OpenResty 构建实时股票信息服务,
这些接口是其中流量最大的,</p>
<p>还有用来发布实时天气信息接口的...</p>
<p>等等吧, OpenResty 的应用可能是无限的.</p>
<p><img alt="p21" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide21_Web-Gateways.png"/></p>
<p>另外一个 OpenResty 的应用场景是 web 网关,
很多 CDN 厂商都在这样使用.</p>
<p>我们还知道有人用 OpenResty 来管理通用 TCP/UDP 流量,</p>
<p>Lua 可以支持你的网关在运行中得以变化,
基于互联网的动态性,
CDN 厂商必须灵活的应对客户的不同需求,
而客户的需求越来越复杂化.</p>
<p>甚至于人们在期待可以包含业务逻辑,比如常见的想动态修订配置文件,来支持软件更新,
等等出于实际需求的要求.</p>
<p>选择 Lua 令一切变的可能,
因为 JIT (即时编译)的机制,
可以随时根据变更的配置生成新的规则,
并根据不同的请求进行对应的流量优化...</p>
<p>NGINX 原先就支持基于 HUP信号 的配置重加载,
但是, 这对于厂商而言成本太高,
因为无法精确的退出相应请求来重启.</p>
<p>另外, 缓存也是个大问题:</p>
<ul>
<li>有时一个客户的缓存非常冷</li>
<li>但是,又不能为了释放这部分数据而重启整个儿缓存</li>
<li>这对其它用户来说太惨了...</li>
</ul>
<p><img alt="p22" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide22_Web-Applications.png"/></p>
<p>OpenResty 原先设计目标是支持完备的web 应用,
第一个案例是网站, 所以,有了 <a href="http://openrety.org">openrety.org</a></p>
<p>如今有越来越多的传统网站,在用 OpenResty 从头开始构建</p>
<p><img alt="p23" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide23_Web-Applications-Products-Details-Page.png"/></p>
<p>例如 京东网, 中国最大的 B2C 电子商务服务平台之一.
在各种营销日, 他们必须面对海量的请求,
类似美国的黑色星期五, 在中国则是 11.11</p>
<p>(<code>是也乎:</code>
问题在中国的光棍节营销流量, 是黑色日期五的几个数量级哪!!!
毕竟, 美国的打折多数是线下的...
)</p>
<p>最早他们使用 Starnet 技术, 经常崩溃,
后来迁移到 JAVA 技术桟, 全然崩溃.</p>
<p>最终迁移到 OpenResty ,虽然后端依然是 JAVA,
但是迎接所有流量的全部是 OpenResty 了, 从此再也没有崩溃过.</p>
<p>现在他们使用 OpenResty 来生成复杂的网页.</p>
<p>比如这个截屏,是 iPhone 的详细产品信息页,
类似页面吸引了主要的流量, 基于 OpenResty 的模板库来生成动态页面,
这是个非常长的页面,只截取了顶部,</p>
<p>他们内部维护了一个非常庞大的模板库,
并用 Redis 来缓存数据 ,以免流量直接击中后端的 JAVA 服务,</p>
<p>春哥曾经询问 JD, 是否需要优化, 他们回答,速度已经足够快, 不用了,谢谢...</p>
<p>(<code>是也乎:</code></p>
<p>这可能是由于性能太好而丢失定制服务的最好案例,
MySQL 只能表示 23333 了...
)</p>
<p><img alt="p24" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide24_OpenResty-Website.png"/></p>
<p>我们自己则重构了官方网站,
整个网站使用 Lua 在 OpenResty 上重写而成,</p>
<p>使用 PorstgreSQL 作为后端数据存储,
通过 OpenResty 直接和数据库交互,</p>
<p>通过 NGINX 的异步非阻塞进程来处理 IO,
非常快速并便宜,</p>
<p>基于 Pg 内置的全文搜索而支持了网站的内部搜索功能.</p>
<p><img alt="p25" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide25_Distributed-Storage-Systems.png"/></p>
<p>这是令春哥自己都惊讶的领域:</p>
<ul>
<li>作为中国最大的网站之一 sina.com</li>
<li>发布有类似 Jawbox 的网络存储产品</li>
<li>他们不仅用 OpenResty 来构建前端</li>
<li>而且还用在后台直接处理文件 I/O</li>
<li>对于这种操作他们非常自得</li>
<li>也非常自豪的成为 OpenReaty 核心组件贡献方之一</li>
</ul>
<p><img alt="p26" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide26_Datanet.png"/></p>
<p>Datanet 则是另外一个类似的项目,
虽然没开源, 但是,作者在努力中,</p>
<p>创始人是 Russell Sullivan,
在 twitter 是 @jaksprats</p>
<p>正在基于 OpenResty 构建一个分布式数据网络,
推荐大家去直接嗯哼...</p>
<p><img alt="p27" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide27_Conflict-Free-Replicated-Data-Types.png"/></p>
<p><code>CRDT</code> ~ 无冲突数据复制类型,
简单的说, 这是全新的复杂理论,
涉及复杂的算法和论文, 还在折腾中...</p>
<p><img alt="p28" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide28_Forming-a-Stateful-Network.png"/></p>
<p>基本上象个 <code>半p2p</code> 网络,
每个节点都可以有状态,通过 类似 p2p 的机制完成自动同步,</p>
<p>为什么叫 <code>半p2p</code> 网络,因为这其中必须有某种中心,
可以是大型数据中心,
以便支持暂时下线的节点, 重新上线时,快速发现差异完成同步....</p>
<p>是的, 机制很复杂要说明白得额外2小时...</p>
<p>(<code>是也乎:</code></p>
<p>不就是不完备的区块链网络嘛...
)</p>
<h3 id="sregex">大事儿: sregex<a class="headerlink" href="#sregex" title="Permanent link">¶</a></h3>
<p><img alt="p29" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide29_Sregex.png"/></p>
<p>sregex <-- 春哥一直在造的轮那 ~ 正则表达式引擎,</p>
<p>当然是为了真实的业务需求</p>
<p>(<code>是也乎:</code></p>
<p>但是,这是阻止不了从头造轮子的快感的...嗯哼!
)</p>
<p><img alt="p30" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide30_web-server.png"/></p>
<p>本质上她必须可以支撑处理流式数据,
毕竟 web 服务器要处理的数据理论上是无限大的.</p>
<p><img alt="p31" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide31_4KB-buffer.png"/></p>
<p>关键问题是高速处理缓冲区块:</p>
<ul>
<li>缓冲总是混沌的</li>
<li>通常很小,比如 4k</li>
<li>数据一进入, 就必须完成处理,得到我们需要的,并作出决定:<ul>
<li>丢弃</li>
<li>或是通过</li>
</ul>
</li>
<li>而且是单向流水线<ul>
<li>一但数据块被处理</li>
<li>立即将被下一组填充</li>
</ul>
</li>
<li>这一构想很得趣, 但是,不简单</li>
<li>算法非常困难, 传统的都不行...</li>
</ul>
<p><img alt="p32" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide32_4KB-buffer-2.png"/></p>
<p>回溯算法在主流正则表达式引擎中很流行,</p>
<p>基本上, 当你找不到匹配时,就将指针逈后移动再重试.</p>
<p>PCRE 以及其它很多引擎都是基于这一算法的,
但是,包含了很多问题,不仅仅是固定缓冲区的要求.</p>
<p>还可能引发非常昂贵的系统资源浪费,
这种现象我们定义为: <code>病理行为</code></p>
<p><img alt="p33" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide33_Xregex%E2%80%99s-BFA-Engine-Performance-Benchmark.png"/></p>
<p>春哥构建了 <a href="https://en.wikipedia.org/wiki/Deterministic_finite_automaton">DFA</a>
(确定性有限自动机),
当前性能尚可, 如图中所示:</p>
<ul>
<li>橙色->Google RE2</li>
<li>紫色->PCRE JIT</li>
<li>黑色->PCRE</li>
<li>绿色->PCRE2解释器</li>
<li>蓝色->PCRE2 JIT</li>
<li>黄色->sregex DFA 原型</li>
</ul>
<p>PCRE 是 C 实现的 Perl 兼容正则表达库,性能口碑很好</p>
<p><img alt="p34" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide34_benchmark2.png"/></p>
<p>在这个有点儿复杂的测试案例中:</p>
<ul>
<li>RE2 比 PCRE 好</li>
<li>甚至于比解释器版本还好</li>
<li>但是, sregex DFA 原型 依然更好点儿</li>
</ul>
<p><img alt="p35" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide35_benchmark3.png"/></p>
<p>而在 <code>/d.*?d/</code> 这一简单案例测试中:</p>
<ul>
<li>我们的原型获得了极大的优势</li>
<li>因为 DFA 可以进行智能优化</li>
</ul>
<p><img alt="p36" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide36_benchmark4.png"/></p>
<p>在 PCRE 提供的性能测试案例集中,
我们(黄色)领先一些</p>
<p><img alt="p37" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide37_benchmark5.png"/></p>
<p>这一正则表达式案例是从 ModSecurity 的核心规则中抽取的,
应用在 WAF(web 应用防火墙)过滤核心中.</p>
<ul>
<li>回溯引擎浪费了大量 CPU 资源,因为在反复回溯</li>
<li>sregex DFA 原型则相反, 非常快</li>
</ul>
<p>sregex 将是 OpenResty 接下来的重心!</p>
<ul>
<li>当前还不是产品状态, 只是个快速原型</li>
<li>春哥用大约2000行 perl 代码实现了一个正则表达式引擎</li>
<li>以便生成能被 clang/GCC 编译的 C 代码</li>
<li>完成这些,只是为了印证设想</li>
</ul>
<p>我们认为:</p>
<div class="highlight"><pre><span></span><code>自己的 JIT 引擎比 Clang/GCC 更好,因为优化器更通用
自己的 JIT 引擎比 Clang/GCC 更好,因为优化器更通用
自己的 JIT 引擎比 Clang/GCC 更好,因为优化器更通用
</code></pre></div>
<p>(<code>好吧, 重要的事儿得说三次</code>)</p>
<h3 id="dsl-lzsql">DSL实验: LZSQL<a class="headerlink" href="#dsl-lzsql" title="Permanent link">¶</a></h3>
<p><img alt="p38" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide38_A-Web-Platform-As-A-Virtual-Machine.png"/></p>
<p>回到主题: 建立在 OpenResty 上的 DSL</p>
<p>先分享了一系列 OpenResty 的新功能,</p>
<p>但是,更重要的是, 春哥认为:</p>
<ul>
<li>OpenResty 可以视作 VM(虚拟机)</li>
<li>就象 JVM</li>
<li>可以更加强大, 更加面向 web</li>
</ul>
<p><img alt="p39" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide39_lz.taobao.com_.png"/></p>
<p>这个实验其实是7~8年前完成的,不算新鲜,但是,实验是值得回味的.</p>
<p>那时春哥供职 taobao, 是 alibaba 集团子公司, 是中国最大的 B2C 平台,
当时在数据分析部门,
客户是 taobao 的商家, 类似 eBay 的商家就是卖家一样.</p>
<p>客户需要一个流量分析工具,
来统计店面的流量,和广告部署/销售间的影响力关系,
这是个非常大的产品.</p>
<p>(<code>是也乎:</code></p>
<p>为什么大? 因为要分析的数据量,相当于好几个 twitter 的数据量....
)</p>
<p><img alt="p40" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide40_Taobao-homepage.png"/></p>
<p>这是产品首页</p>
<p><img alt="p41" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide41_chart.png"/></p>
<p>给出了类似 google 分析样漂亮的图表,
所不同的是有更多数据报告.</p>
<p><img alt="p42" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide42_data-volume.png"/></p>
<p>由于 yaobao 的体量,数据量很大, 非常的大</p>
<p><img alt="p43" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide43_experiment-on-the-client-side.png"/></p>
<p>当时春哥 放胆在客户端进行各种尝试,8年前:</p>
<ul>
<li>整个儿应用逻辑已经全部在前端了</li>
<li>类似 gmail ,完全由一组运行在网页中的脚本构建</li>
<li>还引入了客户端模板:<ul>
<li>构建了一个能从模板生成 JS 代码的引擎</li>
</ul>
</li>
<li>另外也提供了 web 服务来驱动客户端应用</li>
<li>总之, web 服务是关键,是唯一运行在服务器上的东西<ul>
<li>将 JSON 发送给客户端</li>
<li>JS 用编译后的模板生成页面区域</li>
</ul>
</li>
</ul>
<p><img alt="p44" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide44_server-side-.png"/></p>
<p>量子统计整体架构如上:</p>
<ul>
<li>OpenResty 位于后端和浏览器之间</li>
<li>后端是 MySQL 集群,因为数据量大, 光卷就有超过1亿个</li>
<li>另外还有实时统计集群作支撑</li>
<li>同时还作为一个开放平台发布 JSON 的 API</li>
<li>以及 Memcached 和 Tokyo Tyrant 集群来管理其它元数据</li>
<li>但是, 相比其它系统要简洁的多,只用 PHP 来运行</li>
</ul>
<p><img alt="p45" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide45_-Inventing-LZSQL.png"/></p>
<p>春哥很快意识到关键问题:</p>
<ul>
<li>没有足够的人力来支撑开发</li>
<li>整个儿团队只有两个实习生</li>
<li>但是, 不得不将原先 PHP 编写的整个儿数据分析产品迁移到 OpenResty 平台</li>
<li>即使迫使实习生拼命写 Lua 代码,但是,面对复杂到狂乱的业务逻辑,这是个不可能的任务</li>
</ul>
<p>春哥用了一个晚上思考, 决定:</p>
<ul>
<li>基于对数据分析核心模型/模式的理解</li>
<li>构建自己的 DSL</li>
<li>以便用更加自然的形式来描述业务</li>
</ul>
<p>毕竟: <code>什么是编程?</code></p>
<ul>
<li>本质上是和机器对话</li>
<li>令机器理解我们的意图</li>
<li>从而快速/便宜/可靠的完成业务</li>
</ul>
<p>所以, 编程的关键是:</p>
<div class="highlight"><pre><span></span><code>提高同机器对话的效率
</code></pre></div>
<p>那么, 如果你能用两个词或是一个句子来表达一个想法,
为毛要使用十多行代码? 那也忒自虐了!</p>
<p>所以, 春哥不喜欢 JAVA, 因为要输入的代码太多了,
Lua 也不是个好形式, 以及其它现有的所有命令式通用开发语言</p>
<p><img alt="p46" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide46_to-convey-the-idea-to-the-machine.png"/></p>
<p>所以有了第一个 DSL: <code>LZSQL</code></p>
<ul>
<li>基于SQL 的形式, 快速传达想法给系统</li>
<li>为什么选择 SQL ? <ul>
<li>因为数据分析产品本质上是基于关系型数据模型的</li>
<li>无论是否使用 SQL 数据库</li>
</ul>
</li>
<li>我们可以在 SQL 中定义变量和用户变量, 作为第一公民</li>
<li>SQL 可以在一些 MySQL 后端运行</li>
<li>也可以在 NGINX 中运行<ul>
<li>因为实现了包含 SQL 引擎的内存数据库</li>
<li>只有100行左右的 Lua 代码</li>
<li>运行良好</li>
</ul>
</li>
<li>复杂性来源是因为数据不得不来自很多不同的 MySQL 数据库</li>
<li>然后在内存中重新关联, 并组合成最终结果发送到客户端</li>
<li>这其中涉及很多棘手的问题:<ul>
<li>必须能分解 SQL 到不同节点上运行</li>
<li>同时还能自动优化 SQL 查询 <ul>
<li>~ MySQL 自己的优化器通常无法完成海量优化</li>
<li>特别是在 OLAP 场景中</li>
<li>(在线分析过程)</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><img alt="p47" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide47_writing-the-business-logic-in-LZSQL-files.png"/></p>
<p>最终, 实际上我们用 LZSQL 来记述业务逻辑,
用编译器生成 Lua 代码,
在线发布 Lua 代码并运行,
而线上不再需要编译器.</p>
<p>这就是 <code>编译</code> 的美妙所在.</p>
<p><img alt="p48" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide48_to-compile-the-LZSQL-files.png"/></p>
<p>当前的, 提供 CLI 工具,
完成 LZSQL 脚本的编译, 链接到最终 Lua 应用程序.</p>
<p><img alt="p49" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide49_The-result.png"/></p>
<p>其结果非常赞:</p>
<ul>
<li>因为编译器可以进行很多优化</li>
<li>人通常不能, 甚至于不能正确运行</li>
</ul>
<p>旧业务是 PHP 编写的,新接口由春哥编译器生成 Lua 代码,</p>
<ul>
<li>请求延迟下降超过 90%,</li>
<li>甚至于这包含了 MySQL 的延迟,</li>
<li>上图是一次完整的 接口 HTTP 延迟对比</li>
</ul>
<p>值得注意的是, 这时使用的还是标准的 Lua 解释器</p>
<p><img alt="p50" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide50_still-using-the-interpreter-only.png"/></p>
<p>进一步的, 仅仅切换为 LuaJIT , 速度就获得进一步加强</p>
<p><img alt="p51" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide51_4000-lines-of-Perl.png"/></p>
<p>而实际上, LZSQL 编译器,仅仅是 4000行 Perl 代码,
但是,包含了非常复杂的优化和类型检查以及一应上下文相关的分析过程.</p>
<p><img alt="p52" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide52_several-code-emitters.png"/></p>
<p>而且, 编译器包含了:</p>
<ul>
<li>一个解析自己的解析器</li>
<li>一个 AST(抽象语法树)</li>
<li>一堆优化器</li>
<li>一个代码映射器<ul>
<li>其实是多种映射器</li>
<li>因为 LZSQL 支持多种语言后端</li>
</ul>
</li>
</ul>
<p><img alt="p53" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide53_why-not-C-code.png"/></p>
<p>是的, 当时可以生成 Lua 代码,
当然, 也可以生成 C 代码.</p>
<p><img alt="p54" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide54_generate-an-NGINX-model.png"/></p>
<p>是的, 当时后端是一个实时数据库, 提供了非常具体和复杂的线程协议,以至难以人工完成客户端.</p>
<p>但是, 数据库发布有一个完备的wiki 文档:</p>
<ul>
<li>那么为毛不让电脑可以理解文档</li>
<li>自动生成一个 NGINX C 模块来调用呢?</li>
</ul>
<p>于是, 春哥实现了这个想法</p>
<p><img alt="p55" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide55_Ticpy.png"/></p>
<p><img alt="p56" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide56_implementation-example.png"/></p>
<p>是的, 嘦很小的 DSL 抽象就可以解析 wiki 文档.</p>
<p><img alt="p57" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide57_a-very-quick-Perl-script.png"/></p>
<p>于是, 再再再次用 Perl 快速完成了一个编译器来从文档生成 NGINX C 模块,
可以自由的通过 NGINX 来和数据库交互,</p>
<p>这算 NGINC 的上游模块.</p>
<p><img alt="p58" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide58_just-300-lines-of-code.png"/></p>
<p>是的, 文档只有300行, 但是生成的 C 模块有12000行代码.</p>
<p><img alt="p59" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide59_Writing-Programs-to-Write-Programs-to-Write-Programs.png"/></p>
<p>这一案例说明:</p>
<ul>
<li>编程就是和机器沟通</li>
<li>如果文档足够完备</li>
<li>那么完全可以直接转换给机器</li>
<li>从而避免了人工编程的各种糟心事儿</li>
<li>这一切指向了一个觉悟:</li>
</ul>
<p>:</p>
<div class="highlight"><pre><span></span><code>宁愿写程序上编程来生成代码
</code></pre></div>
<p>(<code>是也乎:</code> 也嫑直接写业务代码)</p>
<p><img alt="p60" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide60_Test-Scaffold.png"/></p>
<p>同时我们的测试脚手架也是基于 DSL 的:</p>
<ul>
<li><code>Test::Nginx::Socket</code> 被所有 OpenResty 工程引用</li>
<li>以规范的形式来描述测试用例</li>
</ul>
<p>即使你不会 Perl 也没有关系:</p>
<ul>
<li>嘦按照规范提供描述</li>
<li>服务就能理解并进行对应测试</li>
</ul>
<h3 id="dsl">DSL 的爆发<a class="headerlink" href="#dsl" title="Permanent link">¶</a></h3>
<p><img alt="p61" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide61_How-About-Tests.png"/></p>
<p>幻灯参考: http://search.cpan.org/perldoc?Cheater</p>
<p>接下来的一件大事:</p>
<ul>
<li>对于新产品</li>
<li>数据库中还没有真实的业务数据时</li>
<li>如何进行测试?</li>
<li>我们需要数据来测试 SQL 查询/网页/服务/...</li>
</ul>
<p>所以, 春哥再再再再次用 Perl 实现了一个类似 SQL 语言的建数据表用的 DSL</p>
<p><img alt="p62" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide62_Cheater.png"/></p>
<p>就是 Cheater 工具:</p>
<ul>
<li>用正则表达式来指定允许渲染的字段</li>
<li>并能指定依赖的外链</li>
<li>那么这工具就能生成满足所有约束和要求的随机数据</li>
</ul>
<p><img alt="p63" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide63_The-OpenResty-Model-Language.png"/></p>
<p>回到 OpenResty 场景中, 从多年前的实验中可以学到:</p>
<ul>
<li>可以通过设计/实现模式语言来简化开发</li>
<li>可以在 OpenResty 中使用 SQL </li>
<li>编译器知道在哪儿运行:<ul>
<li>本地或是远程</li>
<li>又或是混合</li>
</ul>
</li>
<li>在不同数据库中运行 SQL ,甚至于不一定是关系型数据库</li>
</ul>
<p><img alt="p64" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide64_The-OpenResty-View-Language.png"/></p>
<p>另外, 也发布有 OpenResty View 语言:</p>
<ul>
<li>基于 <a href="https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller">MVC</a> 模型</li>
<li>在 View 层:<ul>
<li>Perl 有 TT2</li>
<li>Python 有 Jinja2</li>
</ul>
</li>
<li>现在有了自己的 DSL 就可以生成客户端 JS 或是服务端 Lua 代码</li>
<li>这是 DSL 的优势</li>
</ul>
<p><img alt="p65" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide65_Jemplate-Lemplate.png"/></p>
<ul>
<li>Jemplate 将 Perl 的 TT2 模板转换为 JS 代码</li>
<li>Lemplate 则编译成 OpenResty Lua 代码</li>
</ul>
<p><img alt="p66" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide66_The-OpenResty-Controller-Language.png"/></p>
<p>这又是一件大事儿</p>
<p><img alt="p67" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide67_it%E2%80%99s-a-Lua-based-language.png"/></p>
<p>看起来是这样的:</p>
<ul>
<li>基于规则的语言<ul>
<li>你只需要描述一系列规则</li>
<li>箭头左侧是谓词, 类似条件</li>
<li>箭头右侧是行为, 比如重定向/返回错误码...</li>
</ul>
</li>
<li>那些谓词其实是无效的 (不会导致执行具体的行动)</li>
<li>编译器进一步优化的话, 就能将机关的谓词合并起来</li>
<li>多数 CDN 业务编辑都可以如此表述<--这就是 CDN 市场的本质</li>
</ul>
<p>不同的商业模式包含共同的内在特性:</p>
<ul>
<li>这是可能的也是可以的</li>
<li>比如数据分析业务共同的模式是关系模式</li>
<li>SQL 语言洽好是这种模式的表述形式</li>
</ul>
<p>对于 CDN 或是 WAF 型的业务:</p>
<ul>
<li>应该就是规则集的模型</li>
<li>理论上是个 <code>前向链专家系统模型</code></li>
</ul>
<p>春哥是 AI 的资深粉丝</p>
<ul>
<li>高中时就研究过各种流派的 AI 实现</li>
<li>当前机器学习是热点</li>
<li>而专家系统是 AI 的分支, 并没有过时</li>
<li>比如说:<ul>
<li>基于 Prolog 的语法解析, 在自然语言研究领域很流行</li>
<li>而语义解析, 则多用 CLISP</li>
</ul>
</li>
<li>70年代 NASA 就折腾过类似的</li>
</ul>
<p><img alt="p68" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide68_remove-all-the-C-comments.png"/></p>
<p>OpenResty 也支持组合多个 正则表达式 来执行复杂的过滤:</p>
<ul>
<li>这样,所有替换在 NGNIX 输出过滤器中<ul>
<li>是缓冲实时完成的</li>
<li>所以, 定长缓冲区, 无限数据流处理</li>
</ul>
</li>
<li>非常 COOL , 不是嘛?</li>
</ul>
<p>上图是批量从 C++ 中删除注释的案例</p>
<ul>
<li>你可以稍微修订就能支持 CSS/JS 的注释删除</li>
<li>当然的,这是基于 sregex 的</li>
</ul>
<p><img alt="p69" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide69_-WAF-Hot.png"/></p>
<p>WAF 是热点, 公司已在为 NGINX 推出 ModSecurity 端口,</p>
<p>春哥看来 WAF 本身就可以基于前述控制语言来完成.</p>
<p><img alt="p70" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide70_ModSecurity-a-Horrible-DSL.png"/></p>
<p>ModSecurity 本身作为 DSL 很可怕</p>
<p><img alt="p71" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide72_-Example-of-a-Poor-Rule.png"/></p>
<p>这是 ModSecurity 一个线路的描述</p>
<p>已经复杂到天际了, 而厂商们还发明了各种更加复杂 WAF 语法,
只是为了表述类似 <code>if-else</code> 的逻辑</p>
<p>那么为什么不创建我们这样简洁的 DSL ?</p>
<p><img alt="p72" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide71_it%E2%80%99s-a-Lua-based-language-2.png"/></p>
<p>这样的语法就干净很多:</p>
<ul>
<li>也支持短路:如果第一条匹配了,就跳过后续的</li>
<li>本质上只是个 <code>if-else</code> 不必要进行深度嵌套</li>
<li>如果查阅其它 CDN 厂商的 VSL 代码<ul>
<li>其实就是一堆堆的 <code>if-else</code></li>
<li>是的, 很疯狂</li>
</ul>
</li>
</ul>
<h3 id="or_2">OR 的目标<a class="headerlink" href="#or_2" title="Permanent link">¶</a></h3>
<p><img alt="p73" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide73_Model-View-Controller.png"/></p>
<ul>
<li>模式 ~ 不同种类的商业系统都有内在相似的模型,从而抽象为一个 DSL</li>
<li>视图 ~ 已经完成很多种模板语言,都是 DSL</li>
<li>控制 ~ 也已经展示了, 通过规则的描述可以简洁的完成 WAF 业务的定义</li>
</ul>
<p><img alt="p74" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide74_SportLang.png"/></p>
<p>运动类游戏当然也可以拥有自己的语言, 来描述业务系统.</p>
<div class="highlight"><pre><span></span><code>还能更 COOL 嘛?
</code></pre></div>
<p>我们作为软件行业的专业人士,
讲真, 强迫其它行业用户(如物理/数学/建筑/哲学...)来使用计算机语言,
这本身算是种耻辱吧.</p>
<p>理想情景中, 我们应该支持用户:</p>
<ul>
<li>使用他们熟悉的领域语言</li>
<li>自然的描述</li>
<li>而机器可以理解并运算</li>
</ul>
<p>而且, 同时:</p>
<ul>
<li>DSL 还包含了大量的自动优化过程</li>
<li>毕竟这不是每个程序猿都知道的技巧</li>
</ul>
<p><img alt="p75" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide75_The-Y-Language.png"/></p>
<p>当前我们内部已经在使用 Y 语言:</p>
<p>这是全新的能调试多种语言的工具, 类似 GDB, SystemTap, LuaJIT</p>
<p><img alt="p76" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide76_CoffeeScript.png"/></p>
<p>另外也支持 CoffeeScript :</p>
<ul>
<li>毕竟 CoffeeScript 很受欢迎</li>
<li>这种 DSL 可以生成 JS</li>
<li>现在我们可以从 CoffeeScript 生成 OpenResty Lua 代码</li>
</ul>
<p><img alt="p77" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide77_A-Meta-DSL.png"/></p>
<p>我们也有元DSL:</p>
<ul>
<li>用来生成其它所有 DSL 的 DSL</li>
<li>包含 元DSL 本身</li>
</ul>
<p>我们还有创建编译器的 DSL, 能生成:</p>
<ul>
<li>DSL 编译器</li>
<li>DSL 优化器</li>
</ul>
<p>Perl 一直是 春哥 的第一序列武器,
但是,并一定是最好的,
最终可能为构建编译创建专用 DSL</p>
<p><img alt="p78" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide78_Clean-Separation.png"/></p>
<p>我们可以在业务描述和业务实现间进行清晰的隔离.</p>
<p>这意味着我们可以一夜之间, 完成业务系统实现技术桟的切换,而不用触动具体的业务代码.</p>
<p>比如说:</p>
<ul>
<li>我们可以将当前运行在 OpenResty 上的业务系统</li>
<li>一键迁移到 C 甚至于汇编代码上</li>
<li>而不会变动业务逻辑</li>
<li>甚至于将来迁移到新技术桟上, 也不用改变业务代码<ul>
<li>只需要编写一个新的后端优化器</li>
<li>并添加到现有的 DSL 编译器中就好</li>
</ul>
</li>
</ul>
<p><img alt="p79" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide79_Compiling-Style-Web-Frameworks.png"/></p>
<p>此外, 我们也将获得全新的 web 应用框架:</p>
<ul>
<li>编译型的</li>
<li>不再依赖一层层的嵌套, 从而令开发运行都越来越慢</li>
</ul>
<p>我们必须同时实现美丽和效率:</p>
<blockquote>
<p>这是未来商业产品级工程的必须特性</p>
</blockquote>
<p><img alt="p80" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide80_The-Best-Language.png"/></p>
<p>最好的语言就是 <code>商业语言</code> 正如春哥意识到的</p>
<p>基于商业语言开发,还有一个好处就是:</p>
<ul>
<li>一但完成了一个 DSL </li>
<li>将一些业务逻辑放入后</li>
<li>如果有幸拿到客户原始需求文档</li>
<li>两厢对比,发现接近</li>
<li>就意味着作对了 ;-)</li>
</ul>
<p>其实, 还有最好的方式来描述具体的领域问题:</p>
<p><img alt="p81" src="https://cdn-1.wp.nginx.com/wp-content/uploads/2017/08/Yichun_Zhang-conf2016-slide81_The-Machine-Truly-Understands-Business-Logic.png"/></p>
<p>是的, 只有机器真正理解你的业务逻辑, 那么:</p>
<ul>
<li>可以获得比以往更多的嗯哼</li>
<li>比如自动生成测试用例</li>
<li>完成上下文分析</li>
<li>或者干脆为你即时生成真正可运行的实例</li>
</ul>
<p>(<code>是也乎:</code></p>
<p>这, 才是 OpenResty 真正的目标:</p>
<blockquote>
<p>逼所有程序猿变成产品经理</p>
</blockquote>
<p>)</p>
<h2 id="tlog">TLog<a class="headerlink" href="#tlog" title="Permanent link">¶</a></h2>
<ul>
<li>.5h 决定嗯哼</li>
<li>2.h 完成上篇</li>
<li>2.5h 完成下篇</li>
</ul>PyQt4 之消失在 Sierra2017-08-08T00:00:00+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2017-08-08:/pyqt4macos.html
<h3 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h3>
<p>最近在折腾 Qt , 因为在 mac 中开发运行在 win10 中,
用 PyQt 是必然选择哪.</p>
<p>只是项目是老坑, 所以,没用 Qt5 技术桟, 还是 Qt4</p>
<h2 id="_2">嗯哼<a class="headerlink" href="#_2" title="Permanent link">¶</a></h2>
<ul>
<li>这天 …</li></ul>
<h3 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h3>
<p>最近在折腾 Qt , 因为在 mac 中开发运行在 win10 中,
用 PyQt 是必然选择哪.</p>
<p>只是项目是老坑, 所以,没用 Qt5 技术桟, 还是 Qt4</p>
<h2 id="_2">嗯哼<a class="headerlink" href="#_2" title="Permanent link">¶</a></h2>
<ul>
<li>这天要折腾 QR 码识别了</li>
<li>运行 <code>brew install zbar</code></li>
<li>然后,各种问题就爆发了,特别是:<ul>
<li><code>libjpeg.8.dylib</code> 加载不到</li>
<li>PyQt4 镜像丢失</li>
<li>...</li>
</ul>
</li>
<li>重新安装 pyqt 时才发现只有 5.1 系列的 Qt/PyQt 可以安装了...</li>
</ul>
<h2 id="_3">原来<a class="headerlink" href="#_3" title="Permanent link">¶</a></h2>
<p>参考:<a href="https://github.com/cartr/homebrew-qt4">cartr/homebrew-qt4: Homebrew tap for Qt4 and dependent formulae on Sierra</a></p>
<ul>
<li><a href="https://github.com/spesmilo/electrum/issues/2001">Build on macOS Sierra 10.12 without pyqt4? · Issue #2001 · spesmilo/electrum</a></li>
<li><a href="https://gist.github.com/robdvr/271e34785c8a43b1e093d2ee8e612aee">How to install QT4, Poppler, and Cairo on MacOS Sierra 10.12</a></li>
<li><a href="https://stackoverflow.com/questions/36615952/how-can-i-install-pyqt4-for-python-2-7">osx - How can i install PyQT4 for Python 2.7? - Stack Overflow</a></li>
</ul>
<p>要想继续嗯哼 PyQt4:</p>
<div class="highlight"><pre><span></span><code><span class="n">brew</span><span class="w"> </span><span class="n">tap</span><span class="w"> </span><span class="n">cartr</span><span class="o">/</span><span class="n">qt4</span>
<span class="n">brew</span><span class="w"> </span><span class="n">tap</span><span class="o">-</span><span class="n">pin</span><span class="w"> </span><span class="n">cartr</span><span class="o">/</span><span class="n">qt4</span>
<span class="n">brew</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">qt</span><span class="mi">@4</span>
<span class="n">brew</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">cartr</span><span class="o">/</span><span class="n">qt4</span><span class="o">/</span><span class="n">pyqt</span><span class="mi">@4</span>
</code></pre></div>
<p>然后继续的:</p>
<div class="highlight"><pre><span></span><code><span class="o">~/</span><span class="p">.</span><span class="n">pyenv</span><span class="o">/</span><span class="n">versions</span><span class="o">/</span><span class="n">uC2710</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">python2</span><span class="mf">.7</span><span class="o">/</span><span class="n">site</span><span class="o">-</span><span class="n">packages</span><span class="err">༽</span>
<span class="err">༄</span><span class="w"> </span><span class="n">ll</span><span class="w"> </span><span class="n">PyQt4</span>
<span class="n">lrwxr</span><span class="o">-</span><span class="n">xr</span><span class="o">-</span><span class="n">x</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">zoomq</span><span class="w"> </span><span class="n">staff</span><span class="w"> </span><span class="mi">66</span><span class="w"> </span><span class="mi">8</span><span class="w"> </span><span class="mi">8</span><span class="w"> </span><span class="mi">21</span><span class="o">:</span><span class="mi">50</span><span class="w"> </span><span class="n">PyQt4</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">pyqt</span><span class="mi">@4</span><span class="o">/</span><span class="mf">4.12</span><span class="n">_1</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">python2</span><span class="mf">.7</span><span class="o">/</span><span class="n">site</span><span class="o">-</span><span class="n">packages</span><span class="o">/</span><span class="n">PyQt4</span><span class="o">/</span>
</code></pre></div>
<p>是的, 要在 pyenv 中使用 brew 安装的 pyqt 得:</p>
<ul>
<li>在对应版本环境的 site-packages 中使用 <code>ln -s</code> 关联到系统环境的库</li>
<li>就 Qt 而言要链接两个东西:<ul>
<li><code>sip.so -> /usr/local/Cellar/sip/4.19.3_1/lib/python2.7/site-packages/sip.so</code></li>
<li><code>PyQt4 -> /usr/local/Cellar/pyqt@4/4.12_1/lib/python2.7/site-packages/PyQt4/</code></li>
</ul>
</li>
</ul>
<p>PS:</p>
<p>同理: OpenCV 也一样:</p>
<ul>
<li>通过 brew 一致安全稳定的自动化编译安装到系统环境中</li>
<li>然后, 手工通过链接形式加载到对应 pyenv 版本环境中</li>
</ul>
<p>所以, macOS 本质是 UNIX 系统,
用 linux 的环境配置思路是好的,
但是,又为了易用, macOS 也进行了各种妥协, 好在程序猿界总是能第一时间给出对应的嗯哼</p>
<p>只是不通过 google 简直了,不知道何时才能从弥散回来的文章中知道嗯哼...</p>
<blockquote>
<p>请上苍保祐能翻墙的人民吧...</p>
</blockquote>
<h2 id="_4">更新<a class="headerlink" href="#_4" title="Permanent link">¶</a></h2>
<ul>
<li>170809 blogging</li>
<li>170808 inti.</li>
</ul>Leo 5.4 theme custom2016-11-17T00:00:00+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2016-11-17:/leo5theme-key-words.html
<h2 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p><a href="http://blog.zoomquiet.io/leo5theme.html">Leo 5.2 theme custom</a></p>
<p>Leo 是灵活的完全 Pythonic 的可定制 <code>文学化编辑环境</code> ...</p>
<p>所以,其定制的进展是无限的...</p>
<h2 id="_2">现象<a class="headerlink" href="#_2" title="Permanent link">¶</a></h2>
<ul>
<li>在完成了基本的 theme 定制 …</li></ul>
<h2 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p><a href="http://blog.zoomquiet.io/leo5theme.html">Leo 5.2 theme custom</a></p>
<p>Leo 是灵活的完全 Pythonic 的可定制 <code>文学化编辑环境</code> ...</p>
<p>所以,其定制的进展是无限的...</p>
<h2 id="_2">现象<a class="headerlink" href="#_2" title="Permanent link">¶</a></h2>
<ul>
<li>在完成了基本的 theme 定制后发现</li>
<li>默认语法元素的颜色,不太理想</li>
<li>特别是: <a href="http://leoeditor.com/cheatsheet.html#id13"><<sections>></sections></a><ul>
<li>可以将下层节点放置在任何想放置的地方的引入点声明</li>
<li>但是,这里 <code><<...>></code> 两端符号的颜色是默认兰色</li>
<li>在暗色背景中看不清楚</li>
</ul>
</li>
<li>可能一时没能找到配置处</li>
</ul>
<h2 id="_3">解决<a class="headerlink" href="#_3" title="Permanent link">¶</a></h2>
<ul>
<li>通过社区列表咨询<ul>
<li>2天后收到各种建议</li>
</ul>
</li>
<li>才知道是俺使用 Leo 的配置文件过老<ul>
<li>导致新版本的全局 theme 定义节点</li>
<li><code>lThemes: copy to last top-level setting in myLeoSettings.leo-->Common to all themes-->Colors for Leo constructs (all themes)</code></li>
<li>没有部署在 <code>@setting</code> 下</li>
</ul>
</li>
<li>立即复制过去<ul>
<li><code>@color section_name_brackets_color = orange</code></li>
<li>就将对应符号颜色定义为 橙色 了...</li>
</ul>
</li>
</ul>
<h2 id="_4">记要<a class="headerlink" href="#_4" title="Permanent link">¶</a></h2>
<ul>
<li>要有信心,可配置的</li>
<li>要认真向社区咨询</li>
<li>要大胆的实验</li>
<li>毕竟,编辑环境任何一点的改进,都对编程过程带来无法衡量的心理支持</li>
</ul>
<h2 id="logging">logging<a class="headerlink" href="#logging" title="Permanent link">¶</a></h2>
<ul>
<li>160921 感觉到问题</li>
<li>161011 有空尝试解决</li>
<li>161111 通过社区解决</li>
<li>161201 才有空补全</li>
</ul>rMBP 坠入纪2016-06-28T00:00:00+08:002016-07-03T22:23:01+08:00Zoom.Quiettag:blog.zoomquiet.io,2016-06-28:/break-into-rMBP13.html
<h1 id="_1">崩<a class="headerlink" href="#_1" title="Permanent link">¶</a></h1>
<p>160625, 一个平常的早晨, 俺的世界崩溃了一大坨...
5年前老婆大人开恩准购的: 高配版, 8G, 512G+256G SSD 的MBP 15吋 无法开机!</p>
<h1 id="_2">溃<a class="headerlink" href="#_2" title="Permanent link">¶</a></h1>
<p>立即去当地 APPLE 维修中心,从机械硬盘 …</p>
<h1 id="_1">崩<a class="headerlink" href="#_1" title="Permanent link">¶</a></h1>
<p>160625, 一个平常的早晨, 俺的世界崩溃了一大坨...
5年前老婆大人开恩准购的: 高配版, 8G, 512G+256G SSD 的MBP 15吋 无法开机!</p>
<h1 id="_2">溃<a class="headerlink" href="#_2" title="Permanent link">¶</a></h1>
<p>立即去当地 APPLE 维修中心,从机械硬盘启动,使用内置硬盘工具检验 SSD 不通过,
现场重新格式化安装, 但是中心没有 10.11 的安装镜像,只能先安装上 10.7.3 的.
回来,一边回忆,一边想整理这5年, 都如何配置出吻合自个儿口味的 MAC 环境的!?</p>
<p>但是, 下午, 相同情景, 再次灰屏,无法启动!
知道没那么简单了....果然,再次去, 发现是长期使用 60W 的电源来驱动 80W 的机器,导致显卡 SSD 都有问题,必须更换主板…</p>
<h1 id="_3">新<a class="headerlink" href="#_3" title="Permanent link">¶</a></h1>
<p>但是! 电脑是一切工作中心环境哪, 没有一个随时可以投入工作的移动环境,
简直好象就是离开了地球一样!</p>
<p>好在老婆大人受不了俺天塌地陷的表情,一个心软,
俺就冲到 澳门 刚刚开启的 APPLE STORE 扛了台全新
rMBP 13吋,16G 内存, 512G SSD ;-)
OS X 10.11 的.</p>
<h1 id="_4">配<a class="headerlink" href="#_4" title="Permanent link">¶</a></h1>
<p>然后, 开始漫长而艰难的重新配置.</p>
<ul>
<li>为毛?! 因为俺没用 TimeMachine 哪…</li>
<li>实在是当初没有合适的移动硬盘, 在家里 FreeBSD 的电脑上远程进行 TimeMachine 备份又太慢.</li>
<li>加之, 积累有关键数据的 <code>rsync</code> 脚本, 可以自动备份所有关键数据;</li>
<li>进一步的, BMP 的皮实是出了名的, TimeMachine 占用空间也是出了名的...</li>
</ul>
<p>一切的一切,导致,重新开始配置时,才发现有多少事儿要折腾!
参考: <a href="http://s5rst.qiniucdn.com/131113-MyTools/index.html">我的工具箱</a></p>
<p>是的, 用15年以上, 来迭代的将自个儿的电脑操作, 融合到一系列工具中, 并训练成了肌肉记忆,
一台全新的优秀的 rMBP 对俺,几乎无法使用.</p>
<h2 id="_5">习惯<a class="headerlink" href="#_5" title="Permanent link">¶</a></h2>
<p>回想一下俺日常每天每时每刻都在使用的习惯操作</p>
<ul>
<li><code>sshvpnJP</code> 快速和 日本 的主机建立 SSH 隧道, 专供 Chrome 进行 gmail 以及其它科学网络使用</li>
<li><code>cmd+Space</code> 切换输入法, 使用 Rime 的 <code>鼠须管</code> 加载从 win98SE 上移植过来的 <code>BXM</code></li>
<li>subl 中 Shift+Ctrl+上下箭头 可以进行纵向的块选择</li>
<li>FireFox 中 right click 的上下文菜单,应该只有俺需要的</li>
<li>FireFox 使用树状结构的 TAB 来管理批量标签页面</li>
<li>有自动根据当前时间调节色温的 Docker 软件</li>
<li>有驻留 Dock 的日历软件,点击就可以看到</li>
<li>有习惯的双窗口文件管理器</li>
<li>…</li>
</ul>
<p>好吧…事实上在 MAC 中的所有操作都进行过精心的配置!</p>
<p>那么,先冷静的规划一下,恢复的顺序和操作以免前后矛盾;</p>
<p>所谓的配置,其实分:</p>
<ul>
<li>系统配置</li>
<li>软件安装</li>
<li>软件定制</li>
<li>shell 定制</li>
</ul>
<p>从逻辑和先后依赖而言,就应该从基础配置到具体配置来,用越来越多的工具来协助自己完成配置;</p>
<h2 id="_6">过程<a class="headerlink" href="#_6" title="Permanent link">¶</a></h2>
<p>简单的回顾一下关键又崩溃的恢复过程</p>
<h3 id="_7">数据<a class="headerlink" href="#_7" title="Permanent link">¶</a></h3>
<p>因为有 2T 的 WD 火线移动硬盘, 所以, 基本上所有数据都有备份,恢复过程中发现缺少的只有:</p>
<ul>
<li>Leo 的默认 workbook.leo 是链接到其它文档的, 但是,用 rsync 时,没有跟随链接,具体指向哪儿忘记了</li>
<li>FIreFox 有大量的扩展以及扩展本身的配置<ul>
<li>但是,杯具的是, FireFox 的配置/扩展/书签 等等用户数据备份一直没有统一的渠道<ul>
<li>要不是用插件完成 比如 <code>FEBE</code></li>
<li>要不对具体的系统文件目录进行备份</li>
<li>要不用专用软件进行</li>
<li>要不是用内置的 box 之流第三方服务进行</li>
</ul>
</li>
<li>一年前 mozilla 终于提出了自运营的云空间,本来以为都能自动备份下来的,,,结果是俺 Naive 了...</li>
<li>重新安装后, 用原先的身份口令无法登录,看页面明显是中国的火狐公司使用了另外一套云空间,而且没有同步原先海外用户认证</li>
<li>好吧, 更加奇葩的是, FireFox 从大陆和官方下载的 MAC 中文版安装包含根本不同!<ul>
<li>大陆的内置了很多类似 好123 的导航页面和服务....</li>
<li>恶心的我…</li>
<li>大陆版 Firefox_latest_mac_47.0.dmg 90Mb_</li>
<li>官方版 Firefox 47.0.dmg 84Mb</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>其它, 下载/工作/文档/图片, 都用 <code>rsync</code> 非常精细的备份在移动硬盘中,
也是用 <code>rsync</code> 一次就可以同步回来;
所以, 512G 硬盘, 实际 499G 空间,
新机到手只用了 18G , OS X 10.11.3 系统以及赠送的 iWorks 系列软件,才占这么少! 良心!</p>
<p>只是运行完数据同步后, 只有 <code>160G</code> 可用了....</p>
<h3 id="_8">系统<a class="headerlink" href="#_8" title="Permanent link">¶</a></h3>
<p>首先, 关闭 Spotlight, 因为没有什么用,将整个儿硬盘设定为隐私就好.
然后, 立即在键盘中,将 <code>caps</code> 设定为 <code>control</code> 这样和 HHKB Lite 的键位感觉就一致了.</p>
<p>根据 <a href="">ZqBXM/mac at master · ZoomQuiet/ZqBXM</a>(https://github.com/ZoomQuiet/ZqBXM/tree/master/mac) 将 Squirrel 安装恢复出来, 首先恢复输入法.</p>
<p>安装 <code>muCommander</code> 进入熟悉的双窗口文件管理器:</p>
<ul>
<li>杯具的是,这货依赖 JAVA</li>
<li>首先要下载 70M 的 javaforosx.dmg</li>
<li>然后才能运行, 更加神奇的是:<ul>
<li>2013 年就已经停止维护了</li>
<li>最高版本 0.9 无法使用</li>
<li>只能先安装 0.85 使用几天后, 再安装 0.9 就又好了...</li>
</ul>
</li>
<li>当前和 TotalCommander 不同, muCommander 实在是非常轻型的管理器</li>
<li>只是有几个特性刚好吻合我的习惯:<ul>
<li>可以精细的定制样式, 指定程序猿字体, theme</li>
<li>能快速记录/调节 目录书签</li>
<li><code>alt+1</code> 给出所有上级目录</li>
<li><code>alt+2</code> 给出最近操作的目录列表</li>
<li><code>alt+4</code> 给出所有书签目录列表</li>
<li><code>alt+5</code> 给出所有有效驱动器列表</li>
<li><code>cltr+l</code> 用 finder 打开当前目录</li>
<li><code>alt+F6</code> 对选定文件进行批量重定名</li>
<li><code>F5</code> 将选定文件复制到另外一个窗口目录</li>
<li><code>F6</code> 将选定文件移动到另外一个窗口目录</li>
<li><code>F7</code> 创建目录</li>
<li>…
在 muCommander 就可以高速整理当前目录, 吻合记忆结构了.</li>
</ul>
</li>
</ul>
<h3 id="_9">浏览器<a class="headerlink" href="#_9" title="Permanent link">¶</a></h3>
<p>安装当前不用说, 为什么要先安装浏览器, 而不是其它必须软件?!
因为, 其它所有配置/软件信息 ,都用 FireFox 的插件 ScrapBook 管理的,
必须恢复私人本地资料库, 才好在以往收集的文档指引下逐一恢复软件配置.</p>
<p>杯具的是, 更多资料都在 GDriver 中, 而进入, 需要翻越, 可翻越依赖浏览器插, 可 Chrome 的插件都在人家的市场中, 嗯哼, Chrome Store 也在墙外.</p>
<p>是也乎,( ̄▽ ̄)</p>
<p>只好, 先从 baidu 搜索到老版本, <code>Proxy_SwitchySharp.crx</code> 拖到扩展页面中,先勉强用起来.
幸好, 因为太常用,也关键, gmail 帐号口令是记下来的, 登录上, 瞬间, chrome 的一切都回来了!</p>
<p>FireFox 就没有这么幸运了...只能人工, 一个个回忆/搜索/安装/配置回来...</p>
<p>用了差不多半天,才将 FireFox 恢复到比较顺手:</p>
<ul>
<li>DownThemAll 高速/分块 下载器</li>
<li>Greasemonkey 神奇的开挂平台</li>
<li><code>CoLT</code> Copy Link Text and Location 可定制的链接复制管理器,可以一键从页面/链接 生成 markdown/rst/html 等等形式的链接, 是文档写作关键支撑工具</li>
<li><code>Enjoy Reading</code>+<code>Tranquility</code> 是云化了的 <code>Readablity</code> 的替代, 可以将页面净化为只有主要内容</li>
<li>以便用 <code>ScrapBook</code> 抓取为本地页面, 然后用目录树的形式来管理, 离线查阅/标记自学<ul>
<li>参考: <a href="">ZoomQuiet.io collection mapping {by gen4dot2htm.py v11.10.27 at:160217 11:09:36,660754}</a>(http://zoomquiet.io/collection.html)</li>
<li>配合自动脚本, 可以随时将积累了 10+年以上, 20Gb, 5+万页网页分享出来</li>
<li>嗯哼,是的, 通过 7牛CDN ;-)</li>
</ul>
</li>
<li><code>It's All Text!</code> 可以用快捷键召唤出任何指定的本地编辑软件,来编辑网页 textarea, 并自动复制回编辑器编辑的内容! 简直是在线文档/issue/wiki 的维护必须工具! 是的大家都在用网页编辑器, 俺可以用 Sublime Text 进行狂速的本地编辑!</li>
<li><code>NoSquint Plus</code> 可以记忆域名的具体缩放比例, rMBP 的分辨率非常大, 但是,默认显示网页时,又总是放大的过大,需要记忆最合适的比例,自动的!</li>
<li><code>Wired-Marker</code> 能对在线页面进行批注, 是对 ScrapBook 的补充</li>
<li><code>uBlock Origin</code> 智能关闭所有 JS 的业务脚本</li>
<li><code>Adblock Plus</code> 智能关闭所有广告 </li>
<li><code>Right Encoding</code> 高速指定网页编码</li>
<li><code>Tree Style Tab</code>+<code>Tab Mix Plus</code> 用树状目录,层级管理有内容关联的标签页面,简直是海量并发挖掘和学习必须的!</li>
<li><a href="">Menu Wizard</a>(https://addons.mozilla.org/zh-CN/firefox/addon/s3menu-wizard/?src=userprofile) 以上扩展,已经向上下文 right click 菜单追加了上百项选项了!<ul>
<li>必须可以实时精简! 菜单精灵,就是这样一种神器,只看自己需要的菜单!</li>
<li>而且作者是名 乌克兰 程序猿,失业在家就靠几项优秀的 FF 插件的捐助来养家, 每年都得捐助几次,,,,</li>
<li>因为, 实在太好用了!!!! </li>
</ul>
</li>
</ul>
<p>但是,依然丢失了积累超过10年的书签…好在其中至少80% 也都失效了....</p>
<p>等等,还有 Chrome 对应的扩展呢:</p>
<ul>
<li>Greasemonkey 神奇的开挂平台,在 Chrome 上是Tampermonkey</li>
<li>为什么你们就是不能加个空格呢? 嗯哼!</li>
<li>uBlock Origin / Adblock Plus同 FF </li>
<li>Proxy SwitchyOmega 嗯哼!</li>
<li>Octotree 为了快速游览 github 仓库代码</li>
<li><code>Create Link</code> <code>CoLT</code> Copy Link Text and Location 的部分替代</li>
<li>Choosy 嗯哼,,,将 链接用指定 应用打开</li>
<li><code>Boomerang for Gmail</code> 神奇的邮件管理增强, 是 GDT 的必须品</li>
</ul>
<h3 id="leo-with-qt">Leo with Qt<a class="headerlink" href="#leo-with-qt" title="Permanent link">¶</a></h3>
<p>文学化编辑环境 <a href="http://wiki.woodpecker.org.cn/moin/LiterateProgramming">LiterateProgramming - Woodpecker Wiki for CPUG</a> </p>
<p>俺用 Leo 来进行所有的软件开发,图书翻译…更加要命的是所有注册口令的管理.
是的没用伟大的 1Password,,, 也是历史原因:</p>
<ul>
<li>开始用 Leo 管理私人口令时,可能还没有 1P 这公司呢....</li>
<li>1P 要銭的…</li>
<li>Leo 中已经积累了上千帐号的口令了...</li>
</ul>
<p>不过, Leo 的历史也很长,第一个版本发布在 1996 年! 以前都是基于 Tk 的, 中文问题很多,
老爷子自学了 Qt, 在 2013 年全面迁移到 Qt 了, 漂亮了很多,但是,安装就麻烦了点儿.</p>
<p>参考:</p>
<ul>
<li><a href="http://support.apple.com/kb/HT5293">About X11 and OS X</a></li>
<li><a href="http://xquartz.macosforge.org/landing/">XQuartz</a></li>
</ul>
<p>具体的:</p>
<ul>
<li>安装 <code>XQuartz-2.7.9.dmg</code></li>
<li>然后用 brew 安装 qt</li>
<li>最后进入具体的python 环境, 比如说 pyenv 管理的版本 python </li>
<li>用 pip 安装 <code>PyQt4</code> 就好</li>
</ul>
<p>然后, Leo 只是一堆 Py 脚本下载下来,
修订一下别名指向就好:</p>
<div class="highlight"><pre><span></span><code>#<span class="w"> </span>\<span class="o">~/</span>.<span class="nv">bashrc</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nv">running</span><span class="w"> </span><span class="nv">Leo</span>
<span class="nv">alias</span><span class="w"> </span><span class="nv">leolanch</span><span class="o">=</span><span class="s2">"python /opt/bin/leo/launchLeo.py \>\> /dev/null 2\>&1 &"</span>
</code></pre></div>
<h3 id="dock">Dock<a class="headerlink" href="#dock" title="Permanent link">¶</a></h3>
<p>是的,人生第一个 APPLE 软件就是为了 Dock 才突破心障的, 然后就开始了 App Store 的无尽挖掘..</p>
<p>当前习惯的组合:</p>
<ul>
<li>Bartender 2 收纳各种图标</li>
<li><code>Battery Health</code>+<code>coconutBattery</code> 关注电池健康</li>
<li><code>Colossus</code> 国人作品,系统状态报告,重要的是实时网速,以及当前 ip</li>
<li><code>Day-O</code> 用 <code>TinyCal</code> 替代, 进行快速日历查阅</li>
<li><code>Spectacle</code> 进行窗口管理</li>
<li><code>Noizio</code> 工作白噪音, 因为 iOS 上买了,桌面也就顺手入了</li>
<li><code>Flux</code> 自动色温调节, 保护视力</li>
<li><code>Caffeine</code> 嗯哼...</li>
<li><code>Choosy</code> 从 Chrome 将链接在 FireFox 打开 这样就完成了, 用 google 搜索, 用 FireFox 的插件收集结果页面到本地长尾研究.</li>
</ul>
<h3 id="app-storebrew">App Store+Brew<a class="headerlink" href="#app-storebrew" title="Permanent link">¶</a></h3>
<p>通过官方 Store 安装, 的好处是不用自行本地备份 app 的安装文件,
恢复系统时可以从已购应用分类中快速指定, 重新自动安装.</p>
<p>当前习惯使用的应用集:</p>
<ul>
<li>系统工具:<ul>
<li>DrCleaner 内存清理</li>
<li>AppCleaner 软件清理</li>
<li>Alfred 效能工具, 虽然购买了专业版, 但是, 工作流并没有用起来</li>
</ul>
</li>
<li>开发工具:<ul>
<li><code>Sublime Text</code> 嚓, 插件仓库简直无法自拔<ul>
<li>大坑,仅仅配置 md 编辑就要有一个固定的顺序,才能获得过的去的编辑体验...</li>
</ul>
</li>
<li><code>iTerm</code> 每天用的那叫个频繁, 和 subl 配置成一样的 theme….</li>
<li><code>Dash</code> 又一款不得不买的 程序猿 必备软件</li>
<li><code>TeamViewer</code> 打死不用 windows, 但是,一定要用也通过远程管理控制!</li>
<li><code>Tincta</code> 编辑器, 支持正则表达式 替换的</li>
<li>git/svn/hg 什么的通过 brew 安装的就不在这儿提及了...</li>
</ul>
</li>
<li>空间工具:<ul>
<li>360云盘/百度云盘 没办法的标配置</li>
<li>Evernote 用来快速收集 微信中的聊天记录</li>
<li>Dropbox 纯粹用来情怀曾经的美好</li>
<li>Xccello 伪装成桌面的 Trello</li>
</ul>
</li>
<li>文档工具:<ul>
<li>OOo 不得不用的 Office 兼容软件</li>
<li>Ulysses 嗯哼, 比 subl 还要性感的跨平台创作环境</li>
<li>1Checker 自学 E文写作工具</li>
<li>XtraFinder 杯具而神奇的注入式 Finder 增强工具</li>
<li>FileZilla 最好用的 FTP 桌面工具</li>
<li>androidfiletransfer 嗯哼</li>
<li>calibre 电子书转换工具</li>
</ul>
</li>
<li>SNS 工具:<ul>
<li>微信/QQ/Telegram 一个不能少</li>
<li>Ali 旺旺 有时和店家沟通,必须</li>
<li>Skye</li>
</ul>
</li>
<li>阅读观看<ul>
<li><code>Xee³</code> 看图</li>
<li>Skitch 标定图</li>
<li>MediaInfo 照片 Meta 信息</li>
<li>CHM View 嗯哼</li>
<li>Simple Comic 嗯哼</li>
<li>Movist/VLC/MPlayerX/MPV 嗯哼</li>
<li>Skim 看 PD</li>
<li>…</li>
</ul>
</li>
</ul>
<h3 id="dev">Dev.<a class="headerlink" href="#dev" title="Permanent link">¶</a></h3>
<p>开发环境哪…</p>
<p>是另外一个故事了, 也是血淋淋的, 简直不忍心回顾了</p>
<h1 id="_10">总结<a class="headerlink" href="#_10" title="Permanent link">¶</a></h1>
<p>经过72小时,近乎 不眠不休的配置,总算将主要的环境配置好了,
其它的随用随安装就好…</p>
<p>就算每5年才可能来这么一次, 再也不想了!
以往, 只有 win->Linux 时差不多也要这么折腾几天,
Linux->Mac 时,几乎,没有什么感觉;
可是 MAC 的硬件切换,怎么就这么痛?!</p>
<p>回想,一定, 主要的折腾是系统和软件的个性配置, 星星点点, 基本都是微小的痛点,
在长期探寻中,找到了合适的方案, 以及操作快捷键, 然后肌肉记忆了下来,
具体如何配置的, 又没有记录, 或是自动化恢复方案, 然后就只能重新从肌肉记忆反推配置...</p>
<p>所以, 一定要长期/坚持/持续/理性 的备份!</p>
<ul>
<li>杯具总是随时可能发生的</li>
<li>面向灾难恢复的备份才是可用的</li>
<li>最快时间恢复原有最好状态的备份才是好的</li>
</ul>
<p>综上, MAC 本来就内置了最好的备份机制: <code>TimeMachine</code></p>
<h2 id="tm">TM<a class="headerlink" href="#tm" title="Permanent link">¶</a></h2>
<p>一定要用! 一定要用! 一定要用! </p>
<ul>
<li>一个专用设备, 官方的 时间胶囊, 进行无线备份</li>
<li>或是大容量高速移动硬盘进行有线备份,只是:<ul>
<li>一定要雷线! 一定要雷线! 一定要雷线!</li>
</ul>
</li>
<li>当前,有条件的,能上 AirPort Time Capsule 就上</li>
</ul>
<p>只是, 一直担心,没有演练过 TimeMachine 的系统恢复哪, 总是对这机制不怎么放心,
怎么破!?</p>
<h1 id="changelog">Changelog<a class="headerlink" href="#changelog" title="Permanent link">¶</a></h1>
<ul>
<li>160703 增补,因为有人说,都是远古工具陈列馆了,不得不将最近引入工具箱的记述上</li>
<li>160701 补全</li>
<li>160628 发布</li>
<li>160627 随笔</li>
<li>160626 开始</li>
</ul>天然样循环2016-05-31T00:00:00+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2016-05-31:/nedbat-loop-iter.html
<p>来自 @nedbat 的分享:</p>
<p><a href="http://nedbatchelder.com/text/iter.html">Ned Batchelder: Loop Like A Native</a></p>
<h2 id="_1">迭代基础<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p>C样:</p>
<div class="highlight"><pre><span></span><code><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span>
<span class="k">while</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nf">len</span><span class="p">(</span><span class="n">my_list</span><span class="p">)</span><span class="err">:</span>
<span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">my_list</span><span class="o">[</span><span class="n">i</span><span class="o">]</span>
<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="n">v</span>
<span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span>
</code></pre></div>
<p>偏门:</p>
<div class="highlight"><pre><span></span><code><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="k">range</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">my_list</span><span class="p">))</span><span class="err">:</span>
<span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">my_list</span><span class="o">[</span><span class="n">i</span><span class="o">]</span>
<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="n">v</span>
</code></pre></div>
<p>蠎样:</p>
<div class="highlight"><pre><span></span><code>for v in my_list:
print …</code></pre></div>
<p>来自 @nedbat 的分享:</p>
<p><a href="http://nedbatchelder.com/text/iter.html">Ned Batchelder: Loop Like A Native</a></p>
<h2 id="_1">迭代基础<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p>C样:</p>
<div class="highlight"><pre><span></span><code><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span>
<span class="k">while</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nf">len</span><span class="p">(</span><span class="n">my_list</span><span class="p">)</span><span class="err">:</span>
<span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">my_list</span><span class="o">[</span><span class="n">i</span><span class="o">]</span>
<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="n">v</span>
<span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span>
</code></pre></div>
<p>偏门:</p>
<div class="highlight"><pre><span></span><code><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="k">range</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">my_list</span><span class="p">))</span><span class="err">:</span>
<span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">my_list</span><span class="o">[</span><span class="n">i</span><span class="o">]</span>
<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="n">v</span>
</code></pre></div>
<p>蠎样:</p>
<div class="highlight"><pre><span></span><code>for v in my_list:
print v
</code></pre></div>
<p>模式:</p>
<div class="highlight"><pre><span></span><code><span class="k">for</span><span class="w"> </span><span class="nv">name</span><span class="w"> </span><span class="nv">in</span><span class="w"> </span><span class="nv">iterable</span>:
<span class="w"> </span><span class="nv">statements</span>
</code></pre></div>
<ul>
<li>可 <code>iterable</code> 的对象可以生成值流</li>
<li>对迭代对象的每次操作</li>
<li>由对象决定是什么值</li>
<li>Python 中太多对象可以直接迭代的...</li>
</ul>
<h3 id="list-elements">list ⇒ elements<a class="headerlink" href="#list-elements" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code><span class="k">for</span><span class="w"> </span><span class="nv">e</span><span class="w"> </span><span class="nv">in</span><span class="w"> </span>[<span class="mi">1</span>,<span class="w"> </span><span class="mi">2</span>,<span class="w"> </span><span class="mi">3</span>,<span class="w"> </span><span class="mi">4</span>]:
<span class="w"> </span><span class="nv">print</span><span class="w"> </span><span class="nv">e</span>
<span class="mi">1</span>
<span class="mi">2</span>
<span class="mi">3</span>
<span class="mi">4</span>
</code></pre></div>
<h3 id="strings-characters">Strings ⇒ characters<a class="headerlink" href="#strings-characters" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code><span class="k">for</span><span class="w"> </span><span class="nv">c</span><span class="w"> </span><span class="nv">in</span><span class="w"> </span><span class="s2">"Hello"</span>:
<span class="w"> </span><span class="nv">print</span><span class="w"> </span><span class="nv">c</span>
<span class="nv">H</span>
<span class="nv">e</span>
<span class="nv">l</span>
<span class="nv">l</span>
<span class="nv">o</span>
</code></pre></div>
<h3 id="dicts-keys">Dicts ⇒ keys<a class="headerlink" href="#dicts-keys" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code><span class="nv">d</span><span class="w"> </span><span class="o">=</span><span class="w"> </span>{<span class="w"> </span><span class="s1">'a'</span>:<span class="w"> </span><span class="mi">1</span>,<span class="w"> </span><span class="s1">'b'</span>:<span class="w"> </span><span class="mi">2</span>,<span class="w"> </span><span class="s1">'c'</span>:<span class="w"> </span><span class="mi">3</span><span class="w"> </span>}
<span class="k">for</span><span class="w"> </span><span class="nv">k</span><span class="w"> </span><span class="nv">in</span><span class="w"> </span><span class="nv">d</span>:
<span class="w"> </span><span class="nv">print</span><span class="w"> </span><span class="nv">k</span>
<span class="nv">a</span>
<span class="nv">c</span>
<span class="nv">b</span>
</code></pre></div>
<ul>
<li>当然顺序是没有的</li>
<li>以及:<ul>
<li><code>for v in d.itervalues():</code></li>
<li><code>for k,v in d.iteritems():</code></li>
<li>专用形式</li>
</ul>
</li>
</ul>
<h3 id="files-lines">Files ⇒ lines<a class="headerlink" href="#files-lines" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code><span class="nv">with</span><span class="w"> </span><span class="nv">open</span><span class="ss">(</span><span class="s2">"gettysburg.txt"</span><span class="ss">)</span><span class="w"> </span><span class="nv">as</span><span class="w"> </span><span class="nv">f</span>:
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nv">line</span><span class="w"> </span><span class="nv">in</span><span class="w"> </span><span class="nv">f</span>:
<span class="w"> </span><span class="nv">print</span><span class="w"> </span><span class="nv">repr</span><span class="ss">(</span><span class="nv">line</span><span class="ss">)</span>
<span class="s1">'Four-score and seven years ago,\n'</span>
<span class="s1">'our fathers brought forth on this continent\n'</span>
<span class="s1">'a new nation,\n'</span>
<span class="s1">'conceived in liberty,\n'</span>
<span class="s1">'and dedicated to the proposition\n'</span>
<span class="s1">'that all men are created equal.\n'</span>
</code></pre></div>
<h3 id="_2">标准库中有趣的迭代<a class="headerlink" href="#_2" title="Permanent link">¶</a></h3>
<p>正则表达式:</p>
<div class="highlight"><pre><span></span><code><span class="k">for</span><span class="w"> </span><span class="n">match</span><span class="w"> </span><span class="n">in</span><span class="w"> </span><span class="n">re</span><span class="p">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">pattern</span><span class="p">,</span><span class="w"> </span><span class="k">string</span><span class="p">)</span><span class="o">:</span>
<span class="w"> </span><span class="p">#</span><span class="w"> </span><span class="n">once</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">each</span><span class="w"> </span><span class="n">regex</span><span class="w"> </span><span class="n">match</span><span class="p">...</span>
</code></pre></div>
<p>文件系统:</p>
<div class="highlight"><pre><span></span><code><span class="k">for</span><span class="w"> </span><span class="nv">root</span>,<span class="w"> </span><span class="nv">dirs</span>,<span class="w"> </span><span class="nv">files</span><span class="w"> </span><span class="nv">in</span><span class="w"> </span><span class="nv">os</span>.<span class="nv">walk</span><span class="ss">(</span><span class="s1">'/some/dir'</span><span class="ss">)</span>:
<span class="w"> </span>#<span class="w"> </span><span class="nv">once</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nv">each</span><span class="w"> </span><span class="nv">sub</span><span class="o">-</span><span class="nv">directory</span>...
</code></pre></div>
<p>迭代工具:</p>
<div class="highlight"><pre><span></span><code><span class="k">for</span> <span class="n">num</span> <span class="ow">in</span> <span class="n">itertools</span><span class="o">.</span><span class="n">count</span><span class="p">():</span>
<span class="c1"># once for each integer... Infinite!</span>
<span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">chain</span><span class="p">,</span> <span class="n">repeat</span><span class="p">,</span> <span class="n">cycle</span>
<span class="n">seq</span> <span class="o">=</span> <span class="n">chain</span><span class="p">(</span><span class="n">repeat</span><span class="p">(</span><span class="mi">17</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span> <span class="n">cycle</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">4</span><span class="p">)))</span>
<span class="k">for</span> <span class="n">num</span> <span class="ow">in</span> <span class="n">seq</span><span class="p">:</span>
<span class="c1"># 17, 17, 17, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, ...</span>
</code></pre></div>
<h3 id="_3">其它的迭代形式<a class="headerlink" href="#_3" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code>new_list = list(iterable)
results = [f(x) for x in iterable]
total = sum(iterable)
smallest = min(iterable)
largest = max(iterable)
combined = "".join(iterable)
</code></pre></div>
<h2 id="_4">基本设问<a class="headerlink" href="#_4" title="Permanent link">¶</a></h2>
<h3 id="q">Q: 如何获得索引号?<a class="headerlink" href="#q" title="Permanent link">¶</a></h3>
<p>别:</p>
<div class="highlight"><pre><span></span><code><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="k">range</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">my_list</span><span class="p">))</span><span class="err">:</span>
<span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">my_list</span><span class="o">[</span><span class="n">i</span><span class="o">]</span>
<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">v</span>
</code></pre></div>
<p>赞:</p>
<div class="highlight"><pre><span></span><code><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">enumerate</span><span class="p">(</span><span class="n">my_list</span><span class="p">):</span>
<span class="w"> </span><span class="nb">print</span><span class="w"> </span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">v</span>
</code></pre></div>
<h4 id="enumerate">enumerate() 制造好用的值对<a class="headerlink" href="#enumerate" title="Permanent link">¶</a></h4>
<div class="highlight"><pre><span></span><code><span class="n">names</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s2">"Eiffel Tower"</span><span class="p">,</span><span class="w"> </span><span class="s2">"Empire State"</span><span class="p">,</span><span class="w"> </span><span class="s2">"Sears Tower"</span><span class="p">]</span>
<span class="n">list</span><span class="p">(</span><span class="n">enumerate</span><span class="p">(</span><span class="n">names</span><span class="p">))</span>
<span class="p">[(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="s1">'Eiffel Tower'</span><span class="p">),</span><span class="w"> </span>
<span class="w"> </span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="s1">'Empire State'</span><span class="p">),</span><span class="w"> </span>
<span class="w"> </span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="s1">'Sears Tower'</span><span class="p">)]</span>
<span class="k">for</span><span class="w"> </span><span class="n">num</span><span class="p">,</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">enumerate</span><span class="p">(</span><span class="n">names</span><span class="p">):</span>
<span class="w"> </span><span class="nb">print</span><span class="w"> </span><span class="n">num</span><span class="p">,</span><span class="w"> </span><span class="n">name</span>
<span class="mi">0</span><span class="w"> </span><span class="n">Eiffel</span><span class="w"> </span><span class="n">Tower</span>
<span class="mi">1</span><span class="w"> </span><span class="n">Empire</span><span class="w"> </span><span class="n">State</span>
<span class="mi">2</span><span class="w"> </span><span class="n">Sears</span><span class="w"> </span><span class="n">Tower</span>
</code></pre></div>
<h4 id="vs">迭代 vs 索引<a class="headerlink" href="#vs" title="Permanent link">¶</a></h4>
<p>受限:</p>
<div class="highlight"><pre><span></span><code><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="k">range</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">my_list</span><span class="p">))</span><span class="err">:</span>
<span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">my_list</span><span class="o">[</span><span class="n">i</span><span class="o">]</span><span class="w"> </span><span class="err">#</span><span class="w"> </span><span class="n">indexing</span><span class="err">!</span>
<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">v</span>
</code></pre></div>
<p>更强:</p>
<div class="highlight"><pre><span></span><code><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">enumerate</span><span class="p">(</span><span class="n">iterable</span><span class="p">):</span>
<span class="w"> </span><span class="nb">print</span><span class="w"> </span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">v</span>
<span class="k">for</span><span class="w"> </span><span class="n">linenum</span><span class="p">,</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">enumerate</span><span class="p">(</span><span class="n">f</span><span class="p">,</span><span class="w"> </span><span class="n">start</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
<span class="w"> </span><span class="c1">#...</span>
</code></pre></div>
<p>C样坏形:</p>
<div class="highlight"><pre><span></span><code><span class="nv">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span>
<span class="k">for</span><span class="w"> </span><span class="nv">v</span><span class="w"> </span><span class="nv">in</span><span class="w"> </span><span class="nv">iterable</span>:
<span class="w"> </span><span class="nv">print</span><span class="w"> </span><span class="nv">i</span>,<span class="w"> </span><span class="nv">v</span>
<span class="w"> </span><span class="nv">i</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span>
</code></pre></div>
<h3 id="q_1">Q: 如何对两个列表循环?<a class="headerlink" href="#q_1" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code><span class="k">names</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">[</span><span class="n">"Eiffel Tower", "Empire State", "Sears Tower"</span><span class="o">]</span>
<span class="n">heights</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">[</span><span class="n">324, 381, 442</span><span class="o">]</span>
<span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="k">range</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="k">names</span><span class="p">))</span><span class="err">:</span>
<span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">names</span><span class="o">[</span><span class="n">i</span><span class="o">]</span>
<span class="w"> </span><span class="n">height</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">heights</span><span class="o">[</span><span class="n">i</span><span class="o">]</span>
<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="ss">"%s: %s meters"</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="p">(</span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">height</span><span class="p">)</span>
<span class="n">Eiffel</span><span class="w"> </span><span class="nl">Tower</span><span class="p">:</span><span class="w"> </span><span class="mi">324</span><span class="w"> </span><span class="n">meters</span>
<span class="n">Empire</span><span class="w"> </span><span class="k">State</span><span class="err">:</span><span class="w"> </span><span class="mi">381</span><span class="w"> </span><span class="n">meters</span>
<span class="n">Sears</span><span class="w"> </span><span class="nl">Tower</span><span class="p">:</span><span class="w"> </span><span class="mi">442</span><span class="w"> </span><span class="n">meters</span>
</code></pre></div>
<h4 id="zip">zip() 生成弱对关系循环<a class="headerlink" href="#zip" title="Permanent link">¶</a></h4>
<p>将一对循环,变成一个流循环:</p>
<div class="highlight"><pre><span></span><code><span class="k">for</span><span class="w"> </span><span class="nv">name</span>,<span class="w"> </span><span class="nv">height</span><span class="w"> </span><span class="nv">in</span><span class="w"> </span><span class="nv">zip</span><span class="ss">(</span><span class="nv">names</span>,<span class="w"> </span><span class="nv">heights</span><span class="ss">)</span>:
<span class="w"> </span><span class="nv">print</span><span class="w"> </span><span class="s2">"%s: %s meters"</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="ss">(</span><span class="nv">name</span>,<span class="w"> </span><span class="nv">height</span><span class="ss">)</span>
<span class="nv">Eiffel</span><span class="w"> </span><span class="nv">Tower</span>:<span class="w"> </span><span class="mi">324</span><span class="w"> </span><span class="nv">meters</span>
<span class="nv">Empire</span><span class="w"> </span><span class="nv">State</span>:<span class="w"> </span><span class="mi">381</span><span class="w"> </span><span class="nv">meters</span>
<span class="nv">Sears</span><span class="w"> </span><span class="nv">Tower</span>:<span class="w"> </span><span class="mi">442</span><span class="w"> </span><span class="nv">meters</span>
</code></pre></div>
<h4 id="dict">dict() 是接收一对流的<a class="headerlink" href="#dict" title="Permanent link">¶</a></h4>
<div class="highlight"><pre><span></span><code>names = ["Eiffel Tower", "Empire State", "Sears Tower"]
heights = [324, 381, 442]
dict(zip(names, heights))
{'Empire State': 381,
'Sears Tower': 442,
'Eiffel Tower': 324}
</code></pre></div>
<h4 id="_5">最赞<a class="headerlink" href="#_5" title="Permanent link">¶</a></h4>
<div class="highlight"><pre><span></span><code>tall_buildings = {
"Empire State": 381, "Sears Tower": 442,
"Burj Khalifa": 828, "Taipei 101": 509,
}
>>> print max(tall_buildings.values())
828
>>> print max(tall_buildings.items(), key=lambda b: b[1])
('Burj Khalifa', 828)
>>> print max(tall_buildings, key=tall_buildings.get)
'Burj Khalifa'
</code></pre></div>
<h2 id="_6">自制迭代<a class="headerlink" href="#_6" title="Permanent link">¶</a></h2>
<h3 id="_7">生成自有迭代<a class="headerlink" href="#_7" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code>nums = [88, 73, 92, 72, 40, 38, 25, 20, 90, 72]
for n in nums:
if n % 2 == 0:
do_something(n)
def evens(stream):
them = []
for n in stream:
if n % 2 == 0:
them.append(n)
return them
for n in evens(nums):
do_something(n)
</code></pre></div>
<h3 id="_8">生成器<a class="headerlink" href="#_8" title="Permanent link">¶</a></h3>
<p>函式返回一个值 --> 生成器生成一个流</p>
<div class="highlight"><pre><span></span><code>def hello_world():
yield "Hello"
yield "world"
for x in hello_world():
print x
Hello
world
</code></pre></div>
<h4 id="evens-generator">Evens generator<a class="headerlink" href="#evens-generator" title="Permanent link">¶</a></h4>
<div class="highlight"><pre><span></span><code>def evens(stream):
for n in stream:
if n % 2 == 0:
yield n
for n in evens(nums):
do_something(n)
</code></pre></div>
<h4 id="_9">对迭代提炼<a class="headerlink" href="#_9" title="Permanent link">¶</a></h4>
<p>~ Abstracting your iteration</p>
<div class="highlight"><pre><span></span><code>f = open("my_config.ini")
for line in f:
line = line.strip()
if line.startswith('#'):
# A comment line, skip it.
continue
if not line:
# A blank line, skip it.
continue
# An interesting line.
do_something(line)
</code></pre></div>
<p>自制生成器:</p>
<div class="highlight"><pre><span></span><code>def interesting_lines(f):
for line in f:
line = line.strip()
if line.startswith('#'):
continue
if not line:
continue
yield line
with open("my_config.ini") as f:
for line in interesting_lines(f):
do_something(line)
with open("my_other.dat") as f2:
for line in interesting_lines(f2):
do_something_else(line)
</code></pre></div>
<h3 id="q_2">Q: 如何从两层循环中退出?<a class="headerlink" href="#q_2" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code>for row in range(height):
for col in range(width):
value = spreadsheet.get_value(col, row)
do_something(value)
if this_is_my_value(value):
break # ← ???
</code></pre></div>
<h4 id="a">A: 合并循环<a class="headerlink" href="#a" title="Permanent link">¶</a></h4>
<div class="highlight"><pre><span></span><code>def range_2d(width, height):
"""Produce a stream of two-D coordinates."""
for y in range(height):
for x in range(width):
yield x, y
for col, row in range_2d(width, height):
value = spreadsheet.get_value(col, row)
do_something(value)
if this_is_my_value(value):
break
</code></pre></div>
<h4 id="better">Better: 单元迭代<a class="headerlink" href="#better" title="Permanent link">¶</a></h4>
<div class="highlight"><pre><span></span><code>for cell in spreadsheet.cells():
value = cell.get_value()
do_something(value)
if this_is_my_value(value):
break
</code></pre></div>
<h2 id="_10">底层迭代<a class="headerlink" href="#_10" title="Permanent link">¶</a></h2>
<ul>
<li>可迭代: 能生成迭代 Iterable: produces an iterator</li>
<li>
<p>迭代器: 生成一个值流 Iterator: produces a stream of values</p>
<p>iterator = iter(iterable) # iterable.<strong>iter</strong>()
value = next(iterator) # iterator.next() or .<strong>next</strong>()
value = next(iterator)
...</p>
</li>
</ul>
<p>迭代器仅有一个操作: <code>next()</code></p>
<h3 id="_11">迭代基层操作<a class="headerlink" href="#_11" title="Permanent link">¶</a></h3>
<p>有时很有用:</p>
<div class="highlight"><pre><span></span><code>with open("blah.dat") as f:
# Read the first line
header_line = next(f)
# Read the rest
for data_line in f:
# ...
</code></pre></div>
<h3 id="_12">构造自制对象可迭代<a class="headerlink" href="#_12" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code><span class="k">class</span> <span class="n">ToDoList</span>(<span class="n">object</span>):
<span class="n">def</span> <span class="n">__init__</span>(<span class="nb">self</span>):
<span class="nb">self</span>.<span class="n">tasks</span> = []
<span class="n">def</span> <span class="n">__iter__</span>(<span class="nb">self</span>):
<span class="k">return</span> <span class="n">iter</span>(<span class="nb">self</span>.<span class="n">tasks</span>)
<span class="nb">todo</span> = <span class="n">ToDoList</span>()
...
<span class="k">for</span> <span class="n">task</span> <span class="nb">in</span> <span class="n">todo:</span>
<span class="c1"># ...</span>
</code></pre></div>
<ul>
<li>仅仅需要定义 <code>__iter__()</code></li>
</ul>
<h4 id="iter"><strong>iter</strong> 生成器<a class="headerlink" href="#iter" title="Permanent link">¶</a></h4>
<div class="highlight"><pre><span></span><code><span class="k">class</span> <span class="n">ToDoList</span>(<span class="n">object</span>):
<span class="n">def</span> <span class="n">__init__</span>(<span class="nb">self</span>):
<span class="nb">self</span>.<span class="n">tasks</span> = []
<span class="n">def</span> <span class="n">__iter__</span>(<span class="nb">self</span>):
<span class="k">for</span> <span class="n">task</span> <span class="nb">in</span> <span class="nb">self</span>.<span class="n">tasks:</span>
<span class="k">if</span> <span class="nb">not</span> <span class="n">task</span>.<span class="n">done:</span>
<span class="nb">yield</span> <span class="n">task</span>
<span class="n">def</span> <span class="nb">all</span>(<span class="nb">self</span>):
<span class="k">return</span> <span class="n">iter</span>(<span class="nb">self</span>.<span class="n">tasks</span>)
<span class="n">def</span> <span class="nb">done</span>(<span class="nb">self</span>):
<span class="k">return</span> (<span class="nb">t</span> <span class="k">for</span> <span class="nb">t</span> <span class="nb">in</span> <span class="nb">self</span>.<span class="n">tasks</span> <span class="k">if</span> <span class="nb">t</span>.<span class="nb">done</span>)
</code></pre></div>
<h2 id="_13">( ̄▽ ̄)<a class="headerlink" href="#_13" title="Permanent link">¶</a></h2>
<ul>
<li>迭代无处不在</li>
<li>Python 内置了干净强大的模型支持迭代</li>
<li>抽象和定制你的迭代吧!</li>
</ul>
<h2 id="_14">是也乎<a class="headerlink" href="#_14" title="Permanent link">¶</a></h2>
<ul>
<li>160613 空先发</li>
<li>160531 动念</li>
</ul>站立式办公环境尝试2016-05-01T00:00:00+08:002016-07-28T17:14:21+08:00Zoom.Quiettag:blog.zoomquiet.io,2016-05-01:/standing-desk-env.html
<h1 id="_1">立<a class="headerlink" href="#_1" title="Permanent link">¶</a></h1>
<p>人之所以为人, 就是因为站立解放了双手, 提升了视野, 刺激了心智, 勃发了野心...</p>
<p>所以,我们用了几亿年进化, 才站立了起来 …</p>
<h1 id="_1">立<a class="headerlink" href="#_1" title="Permanent link">¶</a></h1>
<p>人之所以为人, 就是因为站立解放了双手, 提升了视野, 刺激了心智, 勃发了野心...</p>
<p>所以,我们用了几亿年进化, 才站立了起来,
怎么可以在钢筋洞穴中, 趴回去呢?!</p>
<h2 id="_2">背景<a class="headerlink" href="#_2" title="Permanent link">¶</a></h2>
<ul>
<li>嗯哼,终于有机会 SOHO 很一段时期了</li>
<li>有舒服的 IKEA 沙发, 但是, 为了健康着想, Standing Desk 系统是值得尝试的</li>
<li>另外, 还有个背景条件就是没有专门的书房给俺使用</li>
<li>只有, 床前 110x300cm 的面积可以利用</li>
<li>以及, 预算 5000RMB 是上限!</li>
</ul>
<h2 id="_3">调研<a class="headerlink" href="#_3" title="Permanent link">¶</a></h2>
<ul>
<li>嗯哼, 手上只有一台 2011版的 MBP 15吋高配作为主力工作用机</li>
<li>另外, 有 WACOM Intaus + HHKB lite2 作为输入设备</li>
<li>需要:<ul>
<li>站立式办公桌, 在俺自然站立时 肘高 112cm</li>
<li>可竖立的显示器</li>
<li>可承载 MBP+立式显示器的支架</li>
<li>可以桥接客厅 wifi 到卧室的中继器</li>
</ul>
</li>
<li>简单的说:<ul>
<li>要用尽可能少的预算完成网络+桌面系统的构建</li>
</ul>
</li>
</ul>
<h2 id="_4">下单<a class="headerlink" href="#_4" title="Permanent link">¶</a></h2>
<p>分两次完成了采购</p>
<ul>
<li>实地广州 IKEA 挖掘<ul>
<li>1799 <a href="http://www.ikea.com/cn/zh/catalog/products/S79084964/">SKARSTA 斯卡斯塔 坐/站两用式办公桌 - IKEA</a> 虽然能调节,并高到 120cm , 但是, 太贵放弃</li>
<li>399 <a href="http://www.ikea.com/cn/zh/catalog/products/00279785/">BILLY毕利 书架 - 桦木贴面 - IKEA</a></li>
<li>224 <a href="http://www.ikea.com/cn/en/catalog/products/60251142/">LINNMON Table top - white - IKEA</a> 60*200cm</li>
<li>70*4 <a href="http://www.ikea.com/cn/en/catalog/products/40261627/">GERTON Leg, adjustable - IKEA</a> 高度可调节67~107cm,对于俺的 112cm 肘高有点不够,但是,可以垫足</li>
<li>500元的桌子再配上全新的书架 < 1000</li>
</ul>
</li>
<li>网络搜罗:<ul>
<li>254 <a href="https://www.amazon.cn/UP%E5%9F%83%E6%99%AEOA-7X-%E6%98%BE%E7%A4%BA%E5%99%A8%E7%AC%94%E8%AE%B0%E6%9C%AC%E6%A1%8C%E9%9D%A2%E5%A4%B9%E8%A3%85%E6%94%AF%E6%9E%B6-%E5%85%A8%E7%BB%B4%E5%BA%A6%E5%8F%AF%E8%B0%83-%E9%93%9D%E5%90%88%E9%87%91%E6%89%93%E9%80%A0-%E9%87%91%E5%B1%9E%E9%AA%A8%E6%9E%B6%E5%BA%95%E5%BA%A7/dp/B00LPDK7H2/ref=sr_1_4?ie=UTF8&qid=1469695428&sr=8-4&keywords=%E6%98%BE%E7%A4%BA%E5%99%A8+%E6%94%AF%E6%9E%B6">UP 埃普-UP埃普OA-7X 显示器笔记本桌面夹装支架(双节臂+双节臂) 全维度可调 铝合金打造 金属骨架底座-价格 报价 图片 评测 多少钱</a></li>
<li>2399 <a href="https://www.amazon.cn/gp/product/B019LI414C/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1">Dell 戴尔-戴尔(DELL)UltraSharp U2515H 25英寸16:19 2K宽屏LED背光IPS液晶显示器</a> 虽然一片 BS 的声音,但是,丰富的接口, 内置 USBHUB,以及 雷电接入, 简直就是 MBP 的绝配, 唯一问题是没有音箱,只有一个音频输出...</li>
</ul>
</li>
<li>299 <a href="https://www.amazon.cn/gp/product/B012SI7XYC/ref=oh_aui_detailpage_o02_s00?ie=UTF8&psc=1">NETGEAR 美国网件 R6220 1200M 双频千兆 802.11ac无线路由器</a> 一分銭一分货! 比 Dlink 稳定很多,但是, 同时4台设备看视频什么的,也不行...</li>
<li>299 <a href="https://www.amazon.cn/gp/product/B00R92CL5E/ref=oh_aui_detailpage_o02_s01?ie=UTF8&psc=1">Netgear 美国网件 EX3700 AC750M 无线扩展器</a> 这货的网线只能输入, 不能输出! 放弃,退货</li>
<li>29*3 <a href="https://www.amazon.cn/gp/product/B00AXTUVWU/ref=oh_aui_detailpage_o02_s00?ie=UTF8&psc=1">SANWA LA-FL6-03BK 1.5mm超薄扁平6类线网线</a><ul>
<li>一个给光猫到 AP</li>
<li>一个给中继到 <a href="http://cubieboard.org/">CubieBoard3</a> 家庭服务器</li>
<li>一个准备给 MBP 使用 (结果没想到下个月 MBP 阵亡,升级成了 rMBP 根本就没有网口了..)</li>
</ul>
</li>
<li>99 <a href="https://www.amazon.cn/gp/product/B00WJBVB10/ref=oh_aui_detailpage_o01_s00?ie=UTF8&psc=1">TOTOLINK EX300 通用无线扩展器 中继器</a></li>
</ul>
<h2 id="_5">体验<a class="headerlink" href="#_5" title="Permanent link">¶</a></h2>
<h2 id="_6">是也乎<a class="headerlink" href="#_6" title="Permanent link">¶</a></h2>
<h1 id="changelog">Changelog<a class="headerlink" href="#changelog" title="Permanent link">¶</a></h1>
<ul>
<li>160726 起稿</li>
<li>160601 总结</li>
<li>160501 身动</li>
<li>160401 动心</li>
</ul>如何在 Leo 中协作?!2016-04-17T00:00:00+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2016-04-17:/how2collaborate-with-leo.html
<h1 id="leo">Leo?<a class="headerlink" href="#leo" title="Permanent link">¶</a></h1>
<p>~ 嗯哼</p>
<p>研究什么是 Leo ? 非要一句话说清查的话,只能是:</p>
<ul>
<li><code>纯 Python 构建的文学化编辑环境</code><ul>
<li>好吧, 那什么是 <code>文学化编辑</code> ?</li>
<li>这事儿, 俺就 …</li></ul></li></ul>
<h1 id="leo">Leo?<a class="headerlink" href="#leo" title="Permanent link">¶</a></h1>
<p>~ 嗯哼</p>
<p>研究什么是 Leo ? 非要一句话说清查的话,只能是:</p>
<ul>
<li><code>纯 Python 构建的文学化编辑环境</code><ul>
<li>好吧, 那什么是 <code>文学化编辑</code> ?</li>
<li>这事儿, 俺就没办法说清楚了....</li>
<li>根据俺一向的宣称: <code>教不会别人的,一定也是自己并不真正理解的</code></li>
</ul>
</li>
<li>这点,俺认!<ul>
<li>参考: <a href="http://wiki.woodpecker.org.cn/moin/LeoEnvironment">LeoEnvironment - Woodpecker Wiki for CPUG</a></li>
<li>以及 <a href="http://wiki.woodpecker.org.cn/moin/ZqStudy/MyLearningSkill#Leo">ZqStudy/MyLearningSkill - Woodpecker Wiki for CPUG</a></li>
</ul>
</li>
<li>就知道, 俺从 05 年上了船...就一直反复的四处宣传 Leo 的舒爽...<ul>
<li>可惜,一直就没有找到一个真正 <code>直指人心</code> 的 文学化编辑/程 的描述姿势</li>
</ul>
</li>
</ul>
<p>好吧,再次尝试一下:</p>
<h2 id="literate-programming">Literate Programming<a class="headerlink" href="#literate-programming" title="Permanent link">¶</a></h2>
<p>~ <a href="http://wiki.woodpecker.org.cn/moin/LiterateProgramming">文学编程</a></p>
<p>先请出 <a href="http://leoeditor.com/leo_toc.html">Leo</a> 创始人 令德华(<a href="http://leoeditor.com/ekr.html">Edward K. Ream</a>) </p>
<p>~ 老令公 在 PyCon2013China 大会上分享的视频 <a href="http://zoomq.qiniudn.com/pychina/PyCon2013China/PyConChina2013-EKR-final-v2.mp4">PyConChina2013-EKR-intro-Leo</a></p>
<p>不那么简单的说就是:</p>
<ul>
<li>文学化编程, 超脱具体编程语言的语法规定</li>
<li>以人的思维结构为记述形式, 进行好象文学创作一样的编程!</li>
<li>其具体现实:<ul>
<li>利用类似 <code><<此处有惊喜>></code> 的结构标注符</li>
<li>在源代码中,替代各种级别的代码块</li>
<li>将程序的编写和源文件的储存格式分离了<ul>
<li>在代码撰写界面中,面对的是完全个性化的抽象结构描述</li>
<li>同时,又可以随时进入自定逻辑区间内, 填充标准语法的源代码</li>
<li>最后,自动将所有 结构标注符 在输出的源文件中展开</li>
</ul>
</li>
<li>这样,同时兼顾了人的自然思维表述,和严格语法要求的源代码形式 </li>
</ul>
</li>
<li>是的, 这一思想源自 <img alt="Donald E. Knuth" src="http://www-cs-faculty.stanford.edu/~knuth/chop.gif"/>, 他原创的 WEB 语言最早实现了 文学化编程</li>
<li>Leo 则是 Python 实现的,可能是最易用的 文学化编辑/程 环境!</li>
</ul>
<p><img alt="Leo4" src="http://leoeditor.com/_static/Leo4-80-border.jpg"/></p>
<h2 id="collaborate-problem">collaborate problem<a class="headerlink" href="#collaborate-problem" title="Permanent link">¶</a></h2>
<p>~ 如果前述解释看不懂,那就对了!</p>
<p>但是,不影响,俺的故事分享...</p>
<p>Leo 包含的编程思想这么 bigger ,一般人在 IDE 环境中,当然是无法理解,
也没有动力尝试的...
所以, 早在 2013 年, Leo 列表中, EKR 就有相应思考</p>
<div class="highlight"><pre><span></span><code><span class="n">from</span><span class="o">:</span><span class="w"> </span><span class="n">Edward</span><span class="w"> </span><span class="n">K</span><span class="o">.</span><span class="w"> </span><span class="n">Ream</span><span class="w"> </span><span class="o"><</span><span class="n">edreamleo</span><span class="err">@</span><span class="n">gmail</span><span class="o">.</span><span class="na">com</span><span class="o">></span>
<span class="n">reply</span><span class="o">-</span><span class="n">to</span><span class="o">:</span><span class="w"> </span><span class="n">leo</span><span class="o">-</span><span class="n">editor</span><span class="err">@</span><span class="n">googlegroups</span><span class="o">.</span><span class="na">com</span>
<span class="n">to</span><span class="o">:</span><span class="w"> </span><span class="n">leo</span><span class="o">-</span><span class="n">editor</span><span class="err">@</span><span class="n">googlegroups</span><span class="o">.</span><span class="na">com</span>
<span class="n">date</span><span class="o">:</span><span class="w"> </span><span class="n">Thu</span><span class="o">,</span><span class="w"> </span><span class="n">Oct</span><span class="w"> </span><span class="mi">24</span><span class="o">,</span><span class="w"> </span><span class="mi">2013</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="mi">5</span><span class="o">:</span><span class="mi">33</span><span class="w"> </span><span class="n">PM</span>
<span class="n">subject</span><span class="o">:</span><span class="w"> </span><span class="n">How</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">collaborate</span><span class="w"> </span><span class="n">using</span><span class="w"> </span><span class="n">Leo</span>
</code></pre></div>
<p>为了讨论时,更加友好,老令公 创造了两个人事</p>
<ul>
<li>能享受文学化编程的 Leo 用户 称为 Leonine (L Leo users, Leonard ...)</li>
<li>还没有理解 Leo 的其它程序猿 称为 Nancy (N non-Leo users)</li>
</ul>
<p>当时,大家一致的共识:</p>
<ul>
<li>为了 Leo 良好工作, 最终源代码中包含的 结构注释(Sentinels) 是必须的</li>
<li>但是, 对于 Nancy 而言 Sentinels 是无意义的混乱字符</li>
<li>所以,若要 Leonine 们能和 Nancy 们愉快的一起工作,必须解决这一矛盾!</li>
</ul>
<p>三年前,俺提议的是:</p>
<ul>
<li>利用类似 hg/git 仓库的 hooks 机制</li>
<li>在提交仓库前,通过 hooks 脚本,自动的完成 L->N 两型代码的互转化</li>
<li>确保, Leonine 们在 Leo 中,有正确的团队代码,以及自己的结构记述</li>
<li>同时, Nancy 们永远不知道 Leo 的存在!</li>
</ul>
<p>问题在:</p>
<ul>
<li>版本管理系统很多,每种都有自个儿的 hooks 机制</li>
<li>要想真正实用化这种自动机制, Leo 社区要维护越来越多的 hooks 脚本</li>
<li>同时,还得想办法减少每次进行个团队仓库时的配置工作</li>
<li>嗯哼,想想都是越来越多的任务...</li>
<li>所以,当年 老令公 曰:<ul>
<li>此法妙</li>
<li>然俺无空</li>
<li>谁想上,谁上...</li>
</ul>
</li>
</ul>
<p>PS:
所谓 <code>结构注释</code> 其实就是标准注释,类似:</p>
<div class="highlight"><pre><span></span><code><span class="gh">#</span>@+<<imports>>
<span class="gh">#</span>@+node:zoomq.20160416174346.3: ** <<imports>>
<span class="gh">#</span>@+others
<span class="gh">#</span>@+node:zoomq.20160416174346.4: *3* in-build
<span class="gh">#</span>@+node:zoomq.20160416174346.5: *3* 3party
</code></pre></div>
<p>虽然吻合对应语言的注释约定 (嗯哼, Leo 可以进行任何语言的编程,不仅仅是 Py);
其实,就是将 Leo (.leo 文件本身其实就是 xml) 中,树形节点的结构描述,
转化为线性注释而已.</p>
<h2 id="terror-story">terror story<a class="headerlink" href="#terror-story" title="Permanent link">¶</a></h2>
<p>~ 于是, 发生了这样的恐怖故事...</p>
<p>之前,俺知道 Leo 中有种 <code>@shadow</code> 指令</p>
<ul>
<li>在 Leo 中,标注在文件节点名前</li>
<li>形如: <code>@shadow path/2/foo.py</code></li>
<li>进行保存时,将自动作以下操作:<ul>
<li>在 <code>path/2/</code> 中建立 <code>path/2/.leo_shadow</code> 隐藏目录</li>
<li>在其中输出 <code>path/2/.leo_shadow/xfoo.py</code> 包含 <code>结构注释</code> 的源代码文件</li>
<li>同时输出 <code>path/2/foo.py</code> 干净的,不包含 <code>结构注释</code> 的源代码文件</li>
</ul>
</li>
<li>这样,通过 git 工具提交到团队仓库时<ul>
<li>Leonine 通过 <code>.leo_shadow</code> 中的文件确保 Leo 中结构树的可用</li>
<li>Nancy 们继续用 IDE 环境维护自然的干净的只有语法结构而没有思维结构的源代码文件</li>
</ul>
</li>
</ul>
<p>所以,在团队代码仓库中,俺自信的将 .leo 文件也放了进来,
并对管理的所有代码节点, 前缀了<code>@shadow</code></p>
<p>某天, 快乐的部署了 <code>git-flow</code> 然后,基于 <code>hotfix</code> 流程,进行每天的开发...</p>
<p>杯具就这样种下了:</p>
<ul>
<li>在俺完成了全天的开发,高兴的将上千行代码 <code>git flow hotfix finish</code> 提交时</li>
<li>顺利的话应该是:<ul>
<li>自动合并 <code>hotfix/我的修订</code> 到 <code>develop</code> 以及 <code>master</code> 分支</li>
<li>然后杀掉 <code>hotfix/我的修订</code> 分支</li>
<li>最后,人工切换到 <code>master</code> 分支, <code>git push</code> 就好</li>
</ul>
</li>
<li>残念的是:<ul>
<li>git 无法自动合并,</li>
<li>因为 .leo 文件在几个分支中差异冲突!</li>
</ul>
</li>
<li>好吧, 这是必然的,,,虽然没有人修订 .leo 文件,但是,为了尝试各种代码<ul>
<li>过程中,进行了大量的节点调整</li>
<li>另外, Leo 文件是无法共同维护的</li>
<li>因为,每个人对代码内在逻辑结构的理解是不同的,不能强求</li>
<li>所以, Leo 文件并不必须在仓库中管理</li>
</ul>
</li>
<li>所以, 俺自然的想到移走 .leo 文件, 再议尝试 <code>hotfix finish</code> 就好的哪!<ul>
<li>恐怖的是,打开 Leo 文件,一片空白!</li>
<li>一激动按了保存,连外部的 <code>.leo_shadow</code> 中以及仓库中所有源代码文件也都清空了!</li>
</ul>
</li>
</ul>
<p>傻了几分钟后, 开始补救:</p>
<ul>
<li>当前被 git-flow 自动跳回了 <code>develop</code> 分支</li>
<li>先用 <code>git reset --hard</code> 恢复工作区状态</li>
<li>然后, 切换到 <code>hotfix/我的修订</code> 分支</li>
<li>将所有 <code>@shadow</code> 变成 <code>@nosent</code>, 再保存 .leo 文件<ul>
<li>这才想起来 <code>@shadow</code> 后, Leo 文件中本身就不包含代码文本了</li>
<li>完全依赖 <code>.leo_shadow</code> 中包含 <code>结构注释</code> 的影子文件</li>
<li><code>@nosent</code> 则相反,输出的文件是干净的,所有信息都在 Leo 文件中<ul>
<li>主要问题在, 这是单向的</li>
<li>如果代码在外部,由其它人员修订了</li>
<li>Leo 是无从得知的,只能人工逐点合并进来</li>
<li>当然 <code>@shadow</code> 也有相同问题</li>
</ul>
</li>
</ul>
</li>
<li>再移出 .leo 文件, 修订其中的目录声明</li>
<li>再次 <code>git flow hotfix finish</code> 提交</li>
<li>呜乎, 一切正常了...</li>
</ul>
<h2 id="clean-all">clean all<a class="headerlink" href="#clean-all" title="Permanent link">¶</a></h2>
<p>~ 惊魂稍定,想起来当年的讨论...</p>
<p>先回顾文档,发现:</p>
<ul>
<li><a href="http://leoeditor.com/tutorial-programming.html#summary-clean-vs-file">Programming with Leo — Leo 5.2 documentation</a> 也详细阐述了团队中协同的建议:<ul>
<li>如果全体都用 Leo 那么所有文件节点用 <code>@file</code> 声明</li>
<li>否则,强烈建议 Leonine 用 <code>@clean</code> </li>
</ul>
</li>
<li>因为, 去年刚刚完成了 <a href="http://leoeditor.com/appendices.html#the-mulder-ream-update-algorithm">mulder/ream 更新算法</a><ul>
<li>原来, Leo 一直使用内置的 <code>difflib</code> 模块<ul>
<li>基于 <code>Bernhard Mulder</code> 实现的文本差异算法</li>
<li>自动将包含 <code>结构注释</code> 文件的差异,还原入 Leo 中的节点树</li>
</ul>
</li>
<li>现在, 在以往的基础上, EKR 意识到,这种差异不一定非要在实际文件中记述!</li>
<li>所以,现在的 <code>@clean</code> 指令进行如下神妙的处理:<ul>
<li>首先,用原先 <code>@file</code> 指令算法将当前最新节点输出为包含 <code>结构注释</code> 的文件</li>
<li>再用相同算法,从外部对应文件读入,解析为 包含 <code>结构注释</code> 的文件</li>
<li>最后,用内置的 <code>difflib</code> 模块对比以上两个文件</li>
<li>获得好似原先,都用 <code>@file</code> 指令进行协同时的差异恢复序列</li>
<li>将外部差异,从 无 <code>结构注释</code> 的文件合并回来!</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><code>ರ_ರ</code> !
这比,俺之前建议的,通过版本系统的 hooks 进行预处理,要更加无感知哪!
老令公的脑洞依然给力哪!</p>
<h2 id="historic">historic<a class="headerlink" href="#historic" title="Permanent link">¶</a></h2>
<p>~ <a href="http://leoeditor.com/history.html#genesis-of-clean">History of Leo — Leo 5.2 documentation</a></p>
<p><img alt="EKR" src="https://d262ilb51hltx0.cloudfront.net/max/700/1*yKVZtcJyfh-FHNEtXrqjPw.jpeg"/> </p>
<ul>
<li>1980 接触了 CWEB</li>
<li>1995 决心实现类似软件</li>
<li>1996~98 在 Apple 的 YellowBox 中尝试</li>
<li>1999~2001 在 Borland C++ 中折腾</li>
<li>2001 遇到 Python,快速基于 Tk 完成了软件原型!</li>
<li>2002 使用 <code>@file</code> 指令来完成代码的汇入/出</li>
<li>2003 迁移工程进入 SourceForge,正式发行 Leo</li>
<li>2004 4.2发布 解决部分 gnx (Global Node Index) 和 uA (User Attributes) 同步问题</li>
<li>2008 增强了几百种功能</li>
<li>2009 终于和 Tk 友尽,全面迁移到 Qt 平台</li>
<li>2014 5.0 发布! 能和 Vim 玩在一起了</li>
<li>2015 5.1 发布, 这年一月的 <code>Aha</code> 事件,激发了 <code>@clean</code> 的诞生<ul>
<li>Leo 就此能真正流行开来了!</li>
</ul>
</li>
</ul>
<p>以及: <a href="http://leoeditor.com/leonine-world.html">The Leonine World — Leo 5.2 documentation</a></p>
<h1 id="summary">summary<a class="headerlink" href="#summary" title="Permanent link">¶</a></h1>
<p>i store up this mail in gmail, but never try to fixed code flow EKR's point.
thanks for EKR's Aha, 3 years question, fixed in Leo 5.2 !
notice this, just after terror story:</p>
<ul>
<li>i always use Leo to develop complex scripts<ul>
<li>when start PyQt4 coding, also base Leo</li>
<li>but, this time under git-flow</li>
</ul>
</li>
<li>even upgrade into Leo 5.2, but my skill stan as 4.0<ul>
<li>as one Leonine, for Nancy in teams</li>
<li>i had usage @shadow</li>
<li>and of course put .leo into git repository too</li>
</ul>
</li>
<li>so in the beginning:<ul>
<li>after 4 hours coding, happy finished one feature develop</li>
<li>base git-flow input:<ul>
<li>$ git flow hotfix finish BIG-FEATURE</li>
</ul>
</li>
<li>as normal git-flow will:<ul>
<li>Latest objects have been fetched from 'origin'</li>
<li>Hotfix branch has been merged into 'master'</li>
<li>The hotfix was tagged 'BIG-FEATURE'</li>
<li>Hotfix branch has been back-merged into 'develop'</li>
<li>Hotfix branch 'hotfix/BIG-FEATURE' has been deleted</li>
</ul>
</li>
<li>BUT!!! because .leo also in git<ul>
<li>and can not Auto-merging with old version</li>
<li>the git-flow hotfix flow break</li>
</ul>
</li>
</ul>
</li>
<li>terror start:<ul>
<li>try move .leo out git repository, and change @path</li>
<li>wants re-write all scripts, merge again</li>
<li>BUT! i forgot @shadown node NOT save data for code</li>
<li>so, after cmd+s, i got empty .py and .leo_shadow/*.py</li>
</ul>
</li>
<li>CAN MOVE minutes for so terror:<ul>
<li>luck remember git keep all verion in breach</li>
<li>so revert develop breach</li>
<li>change back 'hotfix/BIG-FEATURE'<ul>
<li>into .leo change all @shadow to @nosent</li>
<li>move .leo out git repository</li>
<li>chnage @path</li>
</ul>
</li>
<li>re-try <code>$ git flow hotfix finish BIG-FEATURE</code></li>
</ul>
</li>
<li>kill the terror time</li>
</ul>
<p>through this, i learned:</p>
<ul>
<li>.leo is too personal , need not put into git repositry</li>
<li>@shadow is not strong enough</li>
<li>nust use new directive</li>
</ul>
<p>so review leo document, largh in Aha time ;-)
and recheck : <a href="http://leoeditor.com/appendices.html#the-mulder-ream-update-algorithm">Appendices — Leo 5.2 documentation</a></p>
<p>notice @clean, and make confirm in:
Summary: @clean vs @file -> <a href="http://leoeditor.com/tutorial-programming.html#summary-clean-vs-file">Programming with Leo — Leo 5.2 documentation</a></p>
<p>for working with Nancy, i need @clean forever!</p>
<p>BUT the new leo-flow with git-flow is lost one command?</p>
<ul>
<li>how to updating @cloean nodes in Leo? need not to restart Leo?</li>
<li>in my test:<ul>
<li>edit .py out leo, make conflict</li>
<li>try cmd+s, leo alert:</li>
</ul>
</li>
</ul>
<p>... .py
has changed outside Leo.
Overwrite the outline node?</p>
<ul>
<li>but try all kind of command in file menus</li>
<li>not found withch one make Leo :<ul>
<li>read out .py</li>
<li>base The Mulder/Ream algorithm updaing nodes</li>
</ul>
</li>
<li>so i had to clode all Leo windows</li>
<li>restart Leo, so the "Recovered Nodes" auto generated</li>
</ul>
<h1 id="_1">是也乎<a class="headerlink" href="#_1" title="Permanent link">¶</a></h1>
<p>~ 参考俺的有关演讲幻灯: <a href="http://s5rst.qiniucdn.com/131101-leo-china/index.html">Leo</a>
令老爷子,长达42年的编程经历,在不少成品问世,但是,除了维持生计的商业软件,
就是 Leo 这一非常冷门的编辑器软件,
从意动,到越来越易用,坚持了 35 年! 独自坚持完善,改进!</p>
<p><img alt="ekr-github-leo-graphs" src="http://zoomq.qiniudn.com/ZQCollection/snap/leo/ekr-github-leo-graphs.png"/></p>
<p>08年初,工程迁移到 github (<a href="https://github.com/leo-editor/leo-editor/graphs/contributors">leo-editor/leo-editor</a>)至今, 12,815 次提交中,
依然绝大多数是 EKR push 的! </p>
<p>也就是说,还没有另外一位程序猿,能替代已经至少60岁的 令德华(<a href="http://leoeditor.com/ekr.html">Edward K. Ream</a>), 老令公 !!!</p>
<p><img alt="ekr2" src="http://leoeditor.com/ekr2.gif"/></p>
<p>只能祝 <strong>LL&P</strong> 了</p>
<p><code>live long and prosper</code></p>
<ul>
<li>160417 整理分享</li>
<li>160416 惊悚故事</li>
<li>131024 发愿</li>
</ul>Leo 5.2 theme custom2016-04-15T00:00:00+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2016-04-15:/leo5theme.html
<h1 id="en">EN<a class="headerlink" href="#en" title="Permanent link">¶</a></h1>
<p>thanks guys in <code>leo-editor@googlegroups.com</code> :</p>
<ul>
<li>Terry Brown</li>
<li>john lunzer</li>
</ul>
<p>make me know how to custom Leo theme step by step:</p>
<ul>
<li>old versions <code>myLeoSettings.leo</code> appended buttons :<ul>
<li>at <code>leo/myLeoSettings.leo#Startup-->Local buttons</code></li>
<li>need copy from <code>leoSettings.leo</code> </li>
</ul>
</li>
<li>so my custome flow as:<ul>
<li>try edit some node</li>
<li>click …</li></ul></li></ul>
<h1 id="en">EN<a class="headerlink" href="#en" title="Permanent link">¶</a></h1>
<p>thanks guys in <code>leo-editor@googlegroups.com</code> :</p>
<ul>
<li>Terry Brown</li>
<li>john lunzer</li>
</ul>
<p>make me know how to custom Leo theme step by step:</p>
<ul>
<li>old versions <code>myLeoSettings.leo</code> appended buttons :<ul>
<li>at <code>leo/myLeoSettings.leo#Startup-->Local buttons</code></li>
<li>need copy from <code>leoSettings.leo</code> </li>
</ul>
</li>
<li>so my custome flow as:<ul>
<li>try edit some node</li>
<li>click <code>reload-styles</code></li>
<li>open other <code>.leo</code> , check effect</li>
<li>close it</li>
<li>loop up steps</li>
</ul>
</li>
</ul>
<p>finally all i custom in <code>~/.leo/myLeoSettings.leo</code> :</p>
<ul>
<li>appended help menus:<ul>
<li><code>#@settings-->Menus-->@menus-->@menu &Help-->@item open-myLeoSettings-leo</code></li>
</ul>
</li>
<li>bigger cursor:<ul>
<li><code>#@settings-->Qt Gui Misc settings-->@int qt-cursor-width = 6</code></li>
</ul>
</li>
<li>font changed:<ul>
<li><code>#@settings-->Appearance (change these first)-->Qt Gui settings-->Fonts-->Basic Fonts (change these first)-->@string font-family = Input, Droid Sans Mono, DejaVu Sans Mono</code></li>
</ul>
</li>
<li>body-bg dark:<ul>
<li><code>#@settings-->Appearance (change these first)-->Qt Gui settings-->Colors-->Body pane colors-->@color body-bg = #2F3337</code> </li>
</ul>
</li>
<li>close Gutter:<ul>
<li><code>#@settings-->Appearance (change these first)-->Qt Gui settings-->Margins & borders-->Gutter-->@bool use-gutter = False</code></li>
</ul>
</li>
<li>custom border-focus-color:<ul>
<li><code>myLeoSettings.leo#@settings-->Appearance (change these first)-->Qt Gui settings-->Colors-->Border colors-->@color focused-border-focus-color = #85C2FF</code></li>
</ul>
</li>
<li>Python syntax coloring:<ul>
<li><code>#@settings-->Syntax coloring-->Language-specific colors-->Python</code></li>
</ul>
</li>
</ul>
<p>appended nodes:</p>
<div class="highlight"><pre><span></span><code><span class="nv">@color</span><span class="w"> </span><span class="n">blank_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">grey</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">tab_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">red</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">label_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">red</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">keyword1_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#268bd2</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">keyword2_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#2aa198</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">keyword3_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#859900</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">keyword4_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#268bd2</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">literal1_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#cb4b16</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">literal2_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#b58900</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">literal3_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#dc322f</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">literal4_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#859900</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">markup_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#2aa198</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">comment1_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#557755</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">comment2_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#557755</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">comment3_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#557755</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">comment4_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#557755</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">operator_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#bbbbbb</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">function_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#cb4b16</span>
</code></pre></div>
<ul>
<li><code>self</code> with coloring<ul>
<li>fixed <code>path/2/installed/leo/modes/python.py</code></li>
<li>appended <code>"self": "keyword4",</code></li>
</ul>
</li>
</ul>
<h1 id="_1">是也乎<a class="headerlink" href="#_1" title="Permanent link">¶</a></h1>
<p>~ 老问题新解决</p>
<h2 id="_2">背景<a class="headerlink" href="#_2" title="Permanent link">¶</a></h2>
<p><a href="http://leoeditor.com/leo_toc.html">Leo</a> <img alt="Leo4" src="http://leoeditor.com/_static/Leo4-80-border.jpg"/></p>
<ul>
<li>参考: <a href="http://wiki.woodpecker.org.cn/moin/LeoEnvironment">LeoEnvironment - Woodpecker Wiki for CPUG</a></li>
<li>从 05 年开始使用</li>
<li>从笔记到工程管理,都用的非常欢实</li>
<li>是 令德华(<a href="http://leoeditor.com/ekr.html">Edward K. Ream</a>) 独立创建并长期维护的,完备的文学化编辑环境</li>
<li>09年从 Tk 迁移到 Qt 后平滑的跟随俺转战 M$/Ubuntu/MAC 所有桌面系统</li>
<li>嗯哼,完全基于 Python 开发的...</li>
<li>详细介绍,参考 <a href="http://zoomq.qiniudn.com/pychina/PyCon2013China/PyConChina2013-EKR-final-v2.mp4">PyConChina2013-EKR-final-v2</a> ~ 老令公 在 PyCon2013China 大会上分享的视频</li>
</ul>
<h2 id="_3">问题<a class="headerlink" href="#_3" title="Permanent link">¶</a></h2>
<p>但是,使用最性感的编辑器 sublime text 后, 对 Leo 默认的界面就万般难以忍受了...</p>
<p>终于决心折腾一下样式!</p>
<ul>
<li>Leo 基于几个配置文件:<ul>
<li>默认配置 <code>path/2/installed/Leo/config/leoSettings.leo</code></li>
<li>用户配置 <code>~/.leo/myLeoSettings.leo</code></li>
</ul>
</li>
<li>俺从 3.1 版本开始使用 Leo, 现在的稳定版本是 5.2</li>
<li>所以, <code>~/.leo/myLeoSettings.leo</code> 和官方的默认有较大偏差</li>
<li>那么如何解决:<ul>
<li>启用<a href="http://leoeditor.com/what-is-new.html#what-s-new-in-leo-4-11">Leo 4.11</a> 开始有的 <code>sublime Text 2, a dark colorizing theme</code>?</li>
<li>如何令 <code>self</code> 也有语法颜色?</li>
<li>如何改变默认的 <code>cursor</code> 尺寸?</li>
</ul>
</li>
</ul>
<h2 id="_4">过程<a class="headerlink" href="#_4" title="Permanent link">¶</a></h2>
<p>简单的说,手上的配置文件有这几种:</p>
<ul>
<li><code>~/.leo/myLeoSettings.leo</code> 混杂了增补多年配置的可能不兼容配置</li>
<li><code>path/2/installed/Leo/config/leoSettings.leo</code> 5.2 最新版本配置</li>
<li><code>path/2/installed/Leo/config/exampleSettings.leo</code> 5.2 内置配置示例</li>
<li><code>path/2/installed/Leo/config/themes.leo</code> 5.2 内置 theme 定制示例</li>
</ul>
<p>先后进行的尝试:</p>
<ul>
<li>在 <code>exampleSettings.leo</code> 基础上<ul>
<li>先完成积累的习惯配置</li>
<li>再进行 theme 配置</li>
<li>失败! 原先的配置点太多:<ul>
<li>快捷键</li>
<li>窗口布局</li>
<li>字体</li>
<li>颜色</li>
<li>菜单...</li>
</ul>
</li>
</ul>
</li>
<li>在 <code>leoSettings.leo</code> 基础上<ul>
<li>先完成积累的习惯配置</li>
<li>再进行 theme 配置</li>
<li>失败! 原因同上</li>
</ul>
</li>
<li>最终只好一边询问社区列表,一边基于 <code>~/.leo/myLeoSettings.leo</code> 进行配置<ul>
<li>从 <code>leoSettings.leo</code> 复制相应最新配置树过来</li>
<li>参考原先的进行对应配置</li>
</ul>
</li>
</ul>
<h2 id="_5">要点<a class="headerlink" href="#_5" title="Permanent link">¶</a></h2>
<p>~成功将 <img alt="leoeditor" src="http://leoeditor.com/screen-shots/render-svg-sources.png"/>
变成:
<img alt="leo5.2_darktheme" src="http://zoomq.qiniudn.com/ZQCollection/snap/leo/leo5.2_darktheme.png"/></p>
<ul>
<li><code>myLeoSettings.leo</code> 的控制按钮:<ul>
<li>来自 <code>leo/myLeoSettings.leo#Startup-->Local buttons</code>, 要从 <code>leoSettings.leo</code> 复制</li>
<li>这样进行之后的配置尝试时的流程才能固化为:<ul>
<li>进行对应 node 的修订</li>
<li>点击 <code>reload-styles</code></li>
<li>打开另外一个 <code>.leo</code> 观察效果</li>
<li>关闭</li>
<li>重复以上</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>相关 <code>~/.leo/myLeoSettings.leo</code> 的配置点:</p>
<ul>
<li>追加帮助菜单:<ul>
<li><code>#@settings-->Menus-->@menus-->@menu &Help-->@item open-myLeoSettings-leo</code></li>
</ul>
</li>
<li>光标加粗:<ul>
<li><code>#@settings-->Qt Gui Misc settings-->@int qt-cursor-width = 6</code></li>
</ul>
</li>
<li>字体指定:<ul>
<li><code>#@settings-->Appearance (change these first)-->Qt Gui settings-->Fonts-->Basic Fonts (change these first)-->@string font-family = Input, Droid Sans Mono, DejaVu Sans Mono</code></li>
</ul>
</li>
<li>编辑窗口底色:<ul>
<li><code>#@settings-->Appearance (change these first)-->Qt Gui settings-->Colors-->Body pane colors-->@color body-bg = #2F3337</code> </li>
</ul>
</li>
<li>关闭行数:<ul>
<li><code>#@settings-->Appearance (change these first)-->Qt Gui settings-->Margins & borders-->Gutter-->@bool use-gutter = False</code></li>
</ul>
</li>
<li>修订窗格激活提醒框<ul>
<li><code>myLeoSettings.leo#@settings-->Appearance (change these first)-->Qt Gui settings-->Colors-->Border colors-->@color focused-border-focus-color = #85C2FF</code></li>
</ul>
</li>
<li>Python 语法颜色自定:<ul>
<li><code>#@settings-->Syntax coloring-->Language-specific colors-->Python</code></li>
</ul>
</li>
</ul>
<p>逐一追加 node:</p>
<div class="highlight"><pre><span></span><code><span class="nv">@color</span><span class="w"> </span><span class="n">blank_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">grey</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">tab_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">red</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">label_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">red</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">keyword1_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#268bd2</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">keyword2_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#2aa198</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">keyword3_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#859900</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">keyword4_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#268bd2</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">literal1_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#cb4b16</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">literal2_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#b58900</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">literal3_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#dc322f</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">literal4_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#859900</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">markup_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#2aa198</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">comment1_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#557755</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">comment2_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#557755</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">comment3_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#557755</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">comment4_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#557755</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">operator_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#bbbbbb</span>
<span class="nv">@color</span><span class="w"> </span><span class="n">function_color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">#cb4b16</span>
</code></pre></div>
<ul>
<li><code>self</code> 非关键词追加语法颜色<ul>
<li>修订 <code>path/2/installed/leo/modes/python.py</code></li>
<li>追加 <code>"self": "keyword4",</code></li>
</ul>
</li>
</ul>
<p>感谢 <code>leo-editor@googlegroups.com</code> 列表中好人的大力帮助:</p>
<ul>
<li>Terry Brown</li>
<li>john lunzer</li>
</ul>
<h2 id="timing">timing<a class="headerlink" href="#timing" title="Permanent link">¶</a></h2>
<div class="highlight"><pre><span></span><code>+ 1.5h 根据记忆折腾
+ .5h 官方列表提问
+ 2h 使用官方配置折腾
+ 1h 使用列表提示检验
+ .5h 完成心目中的配置
~ 6h 才完成...
</code></pre></div>
<ul>
<li>140909 才算完成一个可以看的版本</li>
<li>140711 完成所有功能,启动文档回顾</li>
</ul>
<h2 id="todo">TODO<a class="headerlink" href="#todo" title="Permanent link">¶</a></h2>
<ul>
<li>subl theme 到 Leo theme 的转换脚本</li>
<li>进一步的样式化:<ul>
<li>髙亮当前行</li>
<li>提纲界面的 dark theme</li>
<li>log 界面的 dark theme</li>
<li>find 界面的 dark theme</li>
<li>...</li>
</ul>
</li>
<li>参考颜色: <a href="http://leo-editor.github.io/snippets/colormap.html">Leo Color Map</a></li>
</ul>Linux 后的思想2016-04-10T00:00:00+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2016-04-10:/linux-linus-not-only-be-fun.html
<p>来自 TED2016 的分享:</p>
<p><a href="https://www.ted.com/talks/linus_torvalds_the_mind_behind_linux">Linus Torvalds: The mind behind Linux | TED Talk | TED.com</a></p>
<p>戳中泪点的:</p>
<ul>
<li>所有项目,只是因为我需要</li>
<li>最困难的不是完成大项目,而是令人们在一 …</li></ul>
<p>来自 TED2016 的分享:</p>
<p><a href="https://www.ted.com/talks/linus_torvalds_the_mind_behind_linux">Linus Torvalds: The mind behind Linux | TED Talk | TED.com</a></p>
<p>戳中泪点的:</p>
<ul>
<li>所有项目,只是因为我需要</li>
<li>最困难的不是完成大项目,而是令人们在一起工作,即使相互不接受</li>
<li>Linux 并不是选择了开源,只是那时刚好有开源吻合 Linux 项目</li>
<li>....</li>
</ul>
<p>是的,为什么 Linux 发展的如此快,而更加早的 GNU 项目反而越来越没有存在感了!?</p>
<ul>
<li>RMS 太聪明,总是戳到关键点</li>
<li>Linus 明智的多,只作自己能控制的,其它的给更加聪明的人折腾吧</li>
<li>嗯哼,这就是失控控制法</li>
<li>不控制的控制才是最好的控制</li>
<li>...</li>
</ul>jump into SSD with Yoesmite2015-04-09T00:00:00+08:002016-06-28T17:24:28+08:00Zoom.Quiettag:blog.zoomquiet.io,2015-04-09:/jump-into-ssd.html
<h1 id="_1">为毛<a class="headerlink" href="#_1" title="Permanent link">¶</a></h1>
<p>不解释, 人家都免费给你升级了哪!</p>
<h1 id="_2">新梗<a class="headerlink" href="#_2" title="Permanent link">¶</a></h1>
<p>~ 嗯哼,各种关键记要,不进行解释了...</p>
<h2 id="npm">npm<a class="headerlink" href="#npm" title="Permanent link">¶</a></h2>
<div class="highlight"><pre><span></span><code><span class="o">$</span><span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">npm</span>
<span class="o">==></span><span class="w"> </span><span class="n">Downloading</span><span class="w"> </span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">homebrew</span><span class="o">.</span><span class="n">bintray</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">bottles</span><span class="o">/</span><span class="n">node</span><span class="o">-</span><span class="mf">0.12</span><span class="o">.</span><span class="mi">2</span><span class="n">_1</span><span class="o">.</span><span class="n">yosemite</span><span class="o">.</span><span class="n">bottle</span><span class="o">.</span><span class="n">tar …</span></code></pre></div>
<h1 id="_1">为毛<a class="headerlink" href="#_1" title="Permanent link">¶</a></h1>
<p>不解释, 人家都免费给你升级了哪!</p>
<h1 id="_2">新梗<a class="headerlink" href="#_2" title="Permanent link">¶</a></h1>
<p>~ 嗯哼,各种关键记要,不进行解释了...</p>
<h2 id="npm">npm<a class="headerlink" href="#npm" title="Permanent link">¶</a></h2>
<div class="highlight"><pre><span></span><code><span class="o">$</span><span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">npm</span>
<span class="o">==></span><span class="w"> </span><span class="n">Downloading</span><span class="w"> </span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">homebrew</span><span class="o">.</span><span class="n">bintray</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">bottles</span><span class="o">/</span><span class="n">node</span><span class="o">-</span><span class="mf">0.12</span><span class="o">.</span><span class="mi">2</span><span class="n">_1</span><span class="o">.</span><span class="n">yosemite</span><span class="o">.</span><span class="n">bottle</span><span class="o">.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
<span class="c1">######################################################################## 100.0%</span>
<span class="o">==></span><span class="w"> </span><span class="n">Pouring</span><span class="w"> </span><span class="n">node</span><span class="o">-</span><span class="mf">0.12</span><span class="o">.</span><span class="mi">2</span><span class="n">_1</span><span class="o">.</span><span class="n">yosemite</span><span class="o">.</span><span class="n">bottle</span><span class="o">.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
<span class="o">==></span><span class="w"> </span><span class="n">Caveats</span>
<span class="n">If</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">update</span><span class="w"> </span><span class="n">npm</span><span class="w"> </span><span class="n">itself</span><span class="p">,</span><span class="w"> </span><span class="n">do</span><span class="w"> </span><span class="n">NOT</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">npm</span><span class="w"> </span><span class="n">update</span><span class="w"> </span><span class="n">command</span><span class="o">.</span>
<span class="n">The</span><span class="w"> </span><span class="n">upstream</span><span class="o">-</span><span class="n">recommended</span><span class="w"> </span><span class="n">way</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">update</span><span class="w"> </span><span class="n">npm</span><span class="w"> </span><span class="k">is</span><span class="p">:</span>
<span class="w"> </span><span class="n">npm</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="o">-</span><span class="n">g</span><span class="w"> </span><span class="n">npm</span><span class="err">@</span><span class="n">latest</span>
</code></pre></div>
<p>Bash completion has been installed to:
/usr/local/etc/bash_completion.d</p>
<p><code>是也乎:</code> 后来也全部升级为 <strong>nvm</strong> 了</p>
<h2 id="subl">subl<a class="headerlink" href="#subl" title="Permanent link">¶</a></h2>
<p>~ <a href="https://segmentfault.com/q/1010000002397241">sublime-text - 如何在mac中用命令行时用sublime打开文件 - SegmentFault</a></p>
<blockquote>
<p>sudo ln -s "/Applications/Sublime\ Text.app/Contents/SharedSupport/bin/subl" /usr/bin/subl</p>
</blockquote>
<h2 id="user">/User<a class="headerlink" href="#user" title="Permanent link">¶</a></h2>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>sudo<span class="w"> </span>mv<span class="w"> </span>/Users<span class="w"> </span>/Users_SSD
$<span class="w"> </span>sudo<span class="w"> </span>ln<span class="w"> </span>-s<span class="w"> </span>/Volumes/Macintosh<span class="se">\ </span>HD/Users/<span class="w"> </span>Users
</code></pre></div>
<h3 id="amd-actionauthenticatesp">AMD-Action:authenticate:SP<a class="headerlink" href="#amd-actionauthenticatesp" title="Permanent link">¶</a></h3>
<p>~ 为了复用原先的配置,结果引发了这个大问题!</p>
<p>参考: <a href="https://grh.am/2015/amd-action-authenticate/">Grh.am - Pesky "AMD-Action:authenticate:SP" and its Fix</a></p>
<p>最后还是小心的对应折腾了一下:</p>
<ul>
<li>将 <code>Users/Shared</code> 中的全部内容 <code>ditto</code> 到 SSD 中</li>
<li>其它的目录,逐一 <code>ln -s</code> 过去</li>
</ul>
<p>这样才好:</p>
<div class="highlight"><pre><span></span><code><span class="o">/</span><span class="n">Users</span><span class="err">༽</span>
<span class="err">༆</span><span class="w"> </span><span class="n">ls</span><span class="w"> </span><span class="o">-</span><span class="mi">1l</span>
<span class="n">Guest</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="p">..</span><span class="o">/</span><span class="n">Users_SSD</span><span class="o">/</span><span class="n">Guest</span><span class="o">/</span>
<span class="kr">Shared</span>
<span class="n">zoomq</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="o">/</span><span class="n">Volumes</span><span class="o">/</span><span class="n">MacintoshHD</span><span class="o">/</span><span class="n">Users</span><span class="o">/</span><span class="n">zoomq</span><span class="o">/</span>
<span class="p">...</span>
</code></pre></div>
<h2 id="xcode">XCode<a class="headerlink" href="#xcode" title="Permanent link">¶</a></h2>
<div class="highlight"><pre><span></span><code>/Volumes/Macintosh\ HD/Applications/Xcode.app/
$ xcode-select --switch /Applications/Xcode.app
</code></pre></div>
<h2 id="svn">svn<a class="headerlink" href="#svn" title="Permanent link">¶</a></h2>
<div class="highlight"><pre><span></span><code><span class="err">$</span><span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">subversion</span>
<span class="o">==></span><span class="w"> </span><span class="n">Installing</span><span class="w"> </span><span class="n">dependencies</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nl">subversion</span><span class="p">:</span><span class="w"> </span><span class="n">openssl</span><span class="p">,</span><span class="w"> </span><span class="n">apr</span><span class="o">-</span><span class="n">util</span><span class="p">,</span><span class="w"> </span><span class="n">readline</span><span class="p">,</span><span class="w"> </span><span class="n">sqlite</span><span class="p">,</span><span class="w"> </span><span class="n">scons</span>
<span class="o">==></span><span class="w"> </span><span class="n">Installing</span><span class="w"> </span><span class="n">subversion</span><span class="w"> </span><span class="nl">dependency</span><span class="p">:</span><span class="w"> </span><span class="n">openssl</span>
<span class="o">==></span><span class="w"> </span><span class="n">Downloading</span><span class="w"> </span><span class="nl">https</span><span class="p">:</span><span class="o">//</span><span class="n">www</span><span class="p">.</span><span class="n">openssl</span><span class="p">.</span><span class="n">org</span><span class="o">/</span><span class="n">source</span><span class="o">/</span><span class="n">openssl</span><span class="o">-</span><span class="mf">1.0.2</span><span class="n">a</span><span class="p">.</span><span class="n">tar</span><span class="p">.</span><span class="n">gz</span>
<span class="n">Already</span><span class="w"> </span><span class="nl">downloaded</span><span class="p">:</span><span class="w"> </span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Caches</span><span class="o">/</span><span class="n">Homebrew</span><span class="o">/</span><span class="n">openssl</span><span class="o">-</span><span class="mf">1.0.2</span><span class="n">a</span><span class="o">-</span><span class="mf">1.</span><span class="n">tar</span><span class="p">.</span><span class="n">gz</span>
<span class="o">==></span><span class="w"> </span><span class="n">perl</span><span class="w"> </span><span class="p">.</span><span class="o">/</span><span class="n">Configure</span><span class="w"> </span><span class="o">--</span><span class="k">prefix</span><span class="o">=/</span><span class="n">opt</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">homebrew</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">openssl</span><span class="o">/</span><span class="mf">1.0.2</span><span class="n">a</span><span class="o">-</span><span class="mi">1</span><span class="w"> </span><span class="o">--</span><span class="n">openssldir</span><span class="o">=/</span><span class="n">Volumes</span><span class="o">/</span><span class="n">Macintosh</span><span class="w"> </span><span class="n">HD</span>
<span class="o">==></span><span class="w"> </span><span class="n">make</span><span class="w"> </span><span class="n">depend</span>
<span class="o">==></span><span class="w"> </span><span class="n">make</span>
<span class="o">==></span><span class="w"> </span><span class="n">make</span><span class="w"> </span><span class="n">test</span>
<span class="o">==></span><span class="w"> </span><span class="n">make</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">MANDIR</span><span class="o">=/</span><span class="n">opt</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">homebrew</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">openssl</span><span class="o">/</span><span class="mf">1.0.2</span><span class="n">a</span><span class="o">-</span><span class="mi">1</span><span class="o">/</span><span class="n">share</span><span class="o">/</span><span class="n">man</span><span class="w"> </span><span class="n">MANSUFFIX</span><span class="o">=</span><span class="n">ssl</span>
<span class="n">installing</span><span class="w"> </span><span class="n">CA</span><span class="p">.</span><span class="n">sh</span>
<span class="k">usage</span><span class="err">:</span><span class="w"> </span><span class="n">cp</span><span class="w"> </span><span class="o">[</span><span class="n">-R [-H | -L | -P</span><span class="o">]</span><span class="err">]</span><span class="w"> </span><span class="o">[</span><span class="n">-fi | -n</span><span class="o">]</span><span class="w"> </span><span class="o">[</span><span class="n">-apvX</span><span class="o">]</span><span class="w"> </span><span class="n">source_file</span><span class="w"> </span><span class="n">target_file</span>
<span class="w"> </span><span class="n">cp</span><span class="w"> </span><span class="o">[</span><span class="n">-R [-H | -L | -P</span><span class="o">]</span><span class="err">]</span><span class="w"> </span><span class="o">[</span><span class="n">-fi | -n</span><span class="o">]</span><span class="w"> </span><span class="o">[</span><span class="n">-apvX</span><span class="o">]</span><span class="w"> </span><span class="n">source_file</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="n">target_directory</span>
<span class="n">make</span><span class="o">[</span><span class="n">1</span><span class="o">]</span><span class="err">:</span><span class="w"> </span><span class="o">***</span><span class="w"> </span><span class="o">[</span><span class="n">install</span><span class="o">]</span><span class="w"> </span><span class="n">Error</span><span class="w"> </span><span class="mi">64</span>
<span class="nl">make</span><span class="p">:</span><span class="w"> </span><span class="o">***</span><span class="w"> </span><span class="o">[</span><span class="n">install_sw</span><span class="o">]</span><span class="w"> </span><span class="n">Error</span><span class="w"> </span><span class="mi">1</span>
</code></pre></div>
<p>READ THIS: https://git.io/brew-troubleshooting</p>
<p>These open issues may also help:
openssl: apply yosemite certificate fix (https://github.com/Homebrew/homebrew/pull/38495)
problems with cert verification by openssl on 10.10.3 (https://github.com/Homebrew/homebrew/issues/38491)
Installing Elixir fails due to OpenSSL errors. (https://github.com/Homebrew/homebrew/issues/33218)
problem with Python 2.7.9 and OpenSSL 1.0.2 (https://github.com/Homebrew/homebrew/issues/38226)</p>
<ul>
<li>参考: <a href="http://subversion.apache.org/packages.html#osx">Apache Subversion Binary Packages</a></li>
<li>Flink/Homebrew 都安装不能</li>
<li>只好使用: <a href="http://www.wandisco.com/subversion/download#osx">WANdisco</a></li>
<li>Subversion-Client-1.8.10_10.10.x</li>
<li>安装成功</li>
</ul>
<h1 id="_3">老梗<a class="headerlink" href="#_3" title="Permanent link">¶</a></h1>
<h2 id="_4">输入法<a class="headerlink" href="#_4" title="Permanent link">¶</a></h2>
<h2 id="brew">brew<a class="headerlink" href="#brew" title="Permanent link">¶</a></h2>
<h2 id="leo">Leo<a class="headerlink" href="#leo" title="Permanent link">¶</a></h2>
<p>The sip-dir for Python is /Volumes/Macintosh HD/Users/zoomq/share/sip.</p>
<p>Python modules have been installed and Homebrew's site-packages is not
in your Python sys.path, so you will not be able to import the modules
this formula installed. If you plan to develop with these modules,
please run:</p>
<div class="highlight"><pre><span></span><code> <span class="n">mkdir</span> <span class="o">-</span><span class="n">p</span> <span class="o">/</span><span class="n">Users</span><span class="o">/</span><span class="n">zoomq</span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Python</span><span class="o">/</span><span class="mf">2.7</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">python</span><span class="o">/</span><span class="n">site</span><span class="o">-</span><span class="n">packages</span>
<span class="n">echo</span> <span class="s1">'import site; site.addsitedir("/Volumes/Macintosh HD/Users/zoomq/lib/python2.7/site-packages")'</span> <span class="o">>></span> <span class="o">/</span><span class="n">Users</span><span class="o">/</span><span class="n">zoomq</span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Python</span><span class="o">/</span><span class="mf">2.7</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">python</span><span class="o">/</span><span class="n">site</span><span class="o">-</span><span class="n">packages</span><span class="o">/</span><span class="n">homebrew</span><span class="o">.</span><span class="n">pth</span>
<span class="o">==></span> <span class="n">Summary</span>
<span class="err">🍺</span> <span class="o">/</span><span class="n">opt</span><span class="o">/</span><span class="nb">bin</span><span class="o">/</span><span class="n">homebrew</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">sip</span><span class="o">/</span><span class="mf">4.16.5</span><span class="p">:</span> <span class="mi">10</span> <span class="n">files</span><span class="p">,</span> <span class="mi">864</span><span class="n">K</span><span class="p">,</span> <span class="n">built</span> <span class="ow">in</span> <span class="mi">5</span> <span class="n">seconds</span>
<span class="err">$</span> <span class="n">brew</span> <span class="n">install</span> <span class="n">pyqt</span>
<span class="o">==></span> <span class="n">Installing</span> <span class="n">pyqt</span> <span class="n">dependency</span><span class="p">:</span> <span class="n">qt</span>
<span class="o">==></span> <span class="n">Downloading</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">download</span><span class="o">.</span><span class="n">qt</span><span class="o">.</span><span class="n">io</span><span class="o">/</span><span class="n">official_releases</span><span class="o">/</span><span class="n">qt</span><span class="o">/</span><span class="mf">4.8</span><span class="o">/</span><span class="mf">4.8.6</span><span class="o">/</span><span class="n">qt</span><span class="o">-</span><span class="n">everywhere</span><span class="o">-</span><span class="n">opensource</span><span class="o">-</span><span class="n">src</span><span class="o">-</span><span class="mf">4.8.6</span><span class="o">.</span><span class="n">tgz</span>
<span class="err">$</span> <span class="n">brew</span> <span class="n">install</span> <span class="n">pyqt</span>
<span class="o">==></span> <span class="n">Downloading</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">downloads</span><span class="o">.</span><span class="n">sf</span><span class="o">.</span><span class="n">net</span><span class="o">/</span><span class="n">project</span><span class="o">/</span><span class="n">pyqt</span><span class="o">/</span><span class="n">PyQt4</span><span class="o">/</span><span class="n">PyQt</span><span class="o">-</span><span class="mf">4.11.3</span><span class="o">/</span><span class="n">PyQt</span><span class="o">-</span><span class="n">mac</span><span class="o">-</span><span class="n">gpl</span><span class="o">-</span><span class="mf">4.11.3</span><span class="o">.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
<span class="n">Already</span> <span class="n">downloaded</span><span class="p">:</span> <span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Caches</span><span class="o">/</span><span class="n">Homebrew</span><span class="o">/</span><span class="n">pyqt</span><span class="o">-</span><span class="mf">4.11.3</span><span class="o">.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
<span class="o">==></span> <span class="n">python</span> <span class="n">configure</span><span class="o">.</span><span class="n">py</span> <span class="o">--</span><span class="n">confirm</span><span class="o">-</span><span class="n">license</span> <span class="o">--</span><span class="n">bindir</span><span class="o">=/</span><span class="n">opt</span><span class="o">/</span><span class="nb">bin</span><span class="o">/</span><span class="n">homebrew</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">pyqt</span><span class="o">/</span><span class="mf">4.11.3</span><span class="o">/</span><span class="nb">bin</span> <span class="o">--</span><span class="n">destdir</span><span class="o">=/</span><span class="n">opt</span>
<span class="n">Error</span><span class="p">:</span> <span class="o">/</span><span class="n">Volumes</span><span class="o">/</span><span class="n">Macintosh</span> <span class="n">HD</span><span class="o">/</span><span class="n">Users</span><span class="o">/</span><span class="n">zoomq</span><span class="o">/</span><span class="n">opt</span><span class="o">/</span><span class="n">qt</span><span class="o">/</span><span class="nb">bin</span><span class="o">/</span><span class="n">qmake</span> <span class="n">failed</span> <span class="n">to</span> <span class="n">create</span> <span class="n">a</span>
<span class="n">makefile</span><span class="o">.</span> <span class="n">Make</span> <span class="n">sure</span> <span class="n">you</span> <span class="n">have</span> <span class="n">a</span> <span class="n">working</span> <span class="n">Qt</span> <span class="n">qmake</span> <span class="n">on</span> <span class="n">your</span> <span class="n">PATH</span> <span class="ow">or</span> <span class="n">use</span> <span class="n">the</span> <span class="o">-</span><span class="n">q</span>
<span class="n">argument</span> <span class="n">to</span> <span class="n">explicitly</span> <span class="n">specify</span> <span class="n">a</span> <span class="n">working</span> <span class="n">Qt</span> <span class="n">qmake</span><span class="o">.</span>
<span class="n">Determining</span> <span class="n">the</span> <span class="n">layout</span> <span class="n">of</span> <span class="n">your</span> <span class="n">Qt</span> <span class="n">installation</span><span class="o">...</span>
<span class="n">READ</span> <span class="n">THIS</span><span class="p">:</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">git</span><span class="o">.</span><span class="n">io</span><span class="o">/</span><span class="n">brew</span><span class="o">-</span><span class="n">troubleshooting</span>
<span class="o">/</span><span class="n">System</span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Frameworks</span><span class="o">/</span><span class="n">Ruby</span><span class="o">.</span><span class="n">framework</span><span class="o">/</span><span class="n">Versions</span><span class="o">/</span><span class="mf">2.0</span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">ruby</span><span class="o">/</span><span class="mf">2.0.0</span><span class="o">/</span><span class="n">net</span><span class="o">/</span><span class="n">http</span><span class="o">.</span><span class="n">rb</span><span class="p">:</span><span class="mi">878</span><span class="p">:</span><span class="ow">in</span> <span class="err">`</span><span class="n">initialize</span><span class="s1">': Failed to connect to: https://api.github.com/search/issues?q=pyqt+repo:Homebrew/homebrew+in:title+state:open&per_page=100 (GitHub::Error)</span>
<span class="n">getaddrinfo</span><span class="p">:</span> <span class="n">nodename</span> <span class="n">nor</span> <span class="n">servname</span> <span class="n">provided</span><span class="p">,</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">known</span>
<span class="err">$</span> <span class="n">brew</span> <span class="n">search</span> <span class="n">qmake</span>
<span class="n">No</span> <span class="n">formula</span> <span class="n">found</span> <span class="k">for</span> <span class="s2">"qmake"</span><span class="o">.</span>
<span class="n">Searching</span> <span class="n">pull</span> <span class="n">requests</span><span class="o">...</span>
<span class="n">Closed</span> <span class="n">pull</span> <span class="n">requests</span><span class="p">:</span>
<span class="n">qmake</span> <span class="n">gets</span> <span class="n">installed</span> <span class="n">by</span> <span class="n">QT</span> <span class="p">(</span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">Homebrew</span><span class="o">/</span><span class="n">homebrew</span><span class="o">/</span><span class="n">pull</span><span class="o">/</span><span class="mi">31336</span><span class="p">)</span>
<span class="n">Added</span> <span class="n">patch</span> <span class="k">for</span> <span class="n">XCode4</span> <span class="n">support</span> <span class="k">for</span> <span class="n">qmake</span><span class="o">.</span> <span class="p">(</span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">Homebrew</span><span class="o">/</span><span class="n">homebrew</span><span class="o">/</span><span class="n">pull</span><span class="o">/</span><span class="mi">10475</span><span class="p">)</span>
<span class="n">PyQT5</span><span class="o">.</span><span class="n">rb</span> <span class="n">Specify</span> <span class="n">qt5</span> <span class="n">version</span> <span class="n">of</span> <span class="n">qmake</span><span class="o">.</span> <span class="p">(</span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">Homebrew</span><span class="o">/</span><span class="n">homebrew</span><span class="o">/</span><span class="n">pull</span><span class="o">/</span><span class="mi">27059</span><span class="p">)</span>
<span class="n">PyQt</span><span class="p">:</span> <span class="n">patch</span> <span class="n">to</span> <span class="n">fix</span> <span class="n">handling</span> <span class="n">of</span> <span class="n">qmake</span> <span class="n">inline</span> <span class="n">comments</span> <span class="p">(</span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">Homebrew</span><span class="o">/</span><span class="n">homebrew</span><span class="o">/</span><span class="n">pull</span><span class="o">/</span><span class="mi">25225</span><span class="p">)</span>
<span class="n">qscintilla2</span><span class="p">:</span> <span class="n">define</span> <span class="mf">10.9</span> <span class="n">qmake</span> <span class="n">make</span> <span class="n">spec</span> <span class="k">for</span> <span class="n">lib</span> <span class="ow">and</span> <span class="n">python</span> <span class="n">module</span> <span class="p">(</span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">Homebrew</span><span class="o">/</span><span class="n">homebrew</span><span class="o">/</span><span class="n">pull</span><span class="o">/</span><span class="mi">25882</span><span class="p">)</span>
</code></pre></div>
<ul>
<li>先安装 <a href="http://xquartz.macosforge.org/landing/">XQuartz</a></li>
<li>重启</li>
</ul>
<p>再:</p>
<div class="highlight"><pre><span></span><code><span class="o">$</span><span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">pyqt</span>
<span class="o">==></span><span class="w"> </span><span class="n">Installing</span><span class="w"> </span><span class="n">pyqt</span><span class="w"> </span><span class="n">dependency</span><span class="p">:</span><span class="w"> </span><span class="n">qt</span>
<span class="o">==></span><span class="w"> </span><span class="n">Downloading</span><span class="w"> </span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">download</span><span class="o">.</span><span class="n">qt</span><span class="o">.</span><span class="n">io</span><span class="o">/</span><span class="n">official_releases</span><span class="o">/</span><span class="n">qt</span><span class="o">/</span><span class="mf">4.8</span><span class="o">/</span><span class="mf">4.8</span><span class="o">.</span><span class="mi">6</span><span class="o">/</span><span class="n">qt</span><span class="o">-</span><span class="n">everywhere</span><span class="o">-</span><span class="n">opensource</span><span class="o">-</span><span class="n">src</span><span class="o">-</span><span class="mf">4.8</span><span class="o">.</span><span class="mf">6.</span><span class="n">t</span>
<span class="n">Already</span><span class="w"> </span><span class="n">downloaded</span><span class="p">:</span><span class="w"> </span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Caches</span><span class="o">/</span><span class="n">Homebrew</span><span class="o">/</span><span class="n">qt</span><span class="o">-</span><span class="mf">4.8</span><span class="o">.</span><span class="mf">6.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
<span class="o">==></span><span class="w"> </span><span class="n">Downloading</span><span class="w"> </span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">raw</span><span class="o">.</span><span class="n">githubusercontent</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">DomT4</span><span class="o">/</span><span class="n">scripts</span><span class="o">/</span><span class="mf">440e3</span><span class="n">cafde5bf6ec6f50cd28fa5bf89c280f1b53</span><span class="o">/</span><span class="n">H</span>
<span class="n">Already</span><span class="w"> </span><span class="n">downloaded</span><span class="p">:</span><span class="w"> </span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Caches</span><span class="o">/</span><span class="n">Homebrew</span><span class="o">/</span><span class="n">qt</span><span class="o">--</span><span class="n">patch</span><span class="o">-</span><span class="mi">57246</span><span class="n">a33460246118a1fab7460c79f2077d3a929</span><span class="o">.</span><span class="n">diff</span>
<span class="o">==></span><span class="w"> </span><span class="n">Patching</span>
<span class="n">patching</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">src</span><span class="o">/</span><span class="n">gui</span><span class="o">/</span><span class="n">dialogs</span><span class="o">/</span><span class="n">qcolordialog_mac</span><span class="o">.</span><span class="n">mm</span>
<span class="n">patching</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">src</span><span class="o">/</span><span class="n">gui</span><span class="o">/</span><span class="n">dialogs</span><span class="o">/</span><span class="n">qfiledialog_mac</span><span class="o">.</span><span class="n">mm</span>
<span class="n">patching</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">src</span><span class="o">/</span><span class="n">gui</span><span class="o">/</span><span class="n">dialogs</span><span class="o">/</span><span class="n">qfontdialog_mac</span><span class="o">.</span><span class="n">mm</span>
<span class="n">patching</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">src</span><span class="o">/</span><span class="n">gui</span><span class="o">/</span><span class="n">kernel</span><span class="o">/</span><span class="n">qapplication_mac</span><span class="o">.</span><span class="n">mm</span>
<span class="n">patching</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">src</span><span class="o">/</span><span class="n">gui</span><span class="o">/</span><span class="n">kernel</span><span class="o">/</span><span class="n">qcocoaapplication_mac</span><span class="o">.</span><span class="n">mm</span>
<span class="n">patching</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">src</span><span class="o">/</span><span class="n">gui</span><span class="o">/</span><span class="n">kernel</span><span class="o">/</span><span class="n">qcocoaapplicationdelegate_mac</span><span class="o">.</span><span class="n">mm</span>
<span class="n">Hunk</span><span class="w"> </span><span class="c1">#4 succeeded at 295 (offset -13 lines).</span>
<span class="n">Hunk</span><span class="w"> </span><span class="c1">#5 succeeded at 342 (offset -13 lines).</span>
<span class="n">patching</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">src</span><span class="o">/</span><span class="n">gui</span><span class="o">/</span><span class="n">kernel</span><span class="o">/</span><span class="n">qcocoaapplicationdelegate_mac_p</span><span class="o">.</span><span class="n">h</span>
<span class="n">patching</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">src</span><span class="o">/</span><span class="n">gui</span><span class="o">/</span><span class="n">kernel</span><span class="o">/</span><span class="n">qcocoamenuloader_mac</span><span class="o">.</span><span class="n">mm</span>
<span class="n">patching</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">src</span><span class="o">/</span><span class="n">gui</span><span class="o">/</span><span class="n">kernel</span><span class="o">/</span><span class="n">qcocoasharedwindowmethods_mac_p</span><span class="o">.</span><span class="n">h</span>
<span class="n">patching</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">src</span><span class="o">/</span><span class="n">gui</span><span class="o">/</span><span class="n">kernel</span><span class="o">/</span><span class="n">qeventdispatcher_mac</span><span class="o">.</span><span class="n">mm</span>
<span class="n">patching</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">src</span><span class="o">/</span><span class="n">gui</span><span class="o">/</span><span class="n">kernel</span><span class="o">/</span><span class="n">qt_cocoa_helpers_mac</span><span class="o">.</span><span class="n">mm</span>
<span class="n">patching</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">src</span><span class="o">/</span><span class="n">gui</span><span class="o">/</span><span class="n">kernel</span><span class="o">/</span><span class="n">qwidget_mac</span><span class="o">.</span><span class="n">mm</span>
<span class="n">patching</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">src</span><span class="o">/</span><span class="n">gui</span><span class="o">/</span><span class="n">styles</span><span class="o">/</span><span class="n">qmacstyle_mac</span><span class="o">.</span><span class="n">mm</span>
<span class="n">patching</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">src</span><span class="o">/</span><span class="n">gui</span><span class="o">/</span><span class="n">util</span><span class="o">/</span><span class="n">qsystemtrayicon_mac</span><span class="o">.</span><span class="n">mm</span>
<span class="n">patching</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">src</span><span class="o">/</span><span class="n">gui</span><span class="o">/</span><span class="n">widgets</span><span class="o">/</span><span class="n">qcocoamenu_mac</span><span class="o">.</span><span class="n">mm</span>
<span class="n">patching</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">src</span><span class="o">/</span><span class="n">gui</span><span class="o">/</span><span class="n">widgets</span><span class="o">/</span><span class="n">qmenu_mac</span><span class="o">.</span><span class="n">mm</span>
<span class="o">==></span><span class="w"> </span><span class="o">./</span><span class="n">configure</span><span class="w"> </span><span class="o">-</span><span class="n">prefix</span><span class="w"> </span><span class="o">/</span><span class="n">opt</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">homebrew</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">qt</span><span class="o">/</span><span class="mf">4.8</span><span class="o">.</span><span class="mi">6</span><span class="w"> </span><span class="o">-</span><span class="n">system</span><span class="o">-</span><span class="n">zlib</span><span class="w"> </span><span class="o">-</span><span class="n">qt</span><span class="o">-</span><span class="n">libtiff</span><span class="w"> </span><span class="o">-</span><span class="n">qt</span><span class="o">-</span><span class="n">libpng</span><span class="w"> </span><span class="o">-</span><span class="n">qt</span><span class="o">-</span><span class="n">libjpeg</span>
<span class="o">==></span><span class="w"> </span><span class="n">make</span>
<span class="o">$</span><span class="w"> </span><span class="n">which</span><span class="w"> </span><span class="n">qmake</span>
<span class="o">/</span><span class="n">Volumes</span><span class="o">/</span><span class="n">Macintosh</span><span class="w"> </span><span class="n">HD</span><span class="o">/</span><span class="n">Users</span><span class="o">/</span><span class="n">zoomq</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">qmake</span>
<span class="o">$</span><span class="w"> </span><span class="o">/</span><span class="n">opt</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">homebrew</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">qt</span><span class="o">/</span><span class="mf">4.8</span><span class="o">.</span><span class="mi">6</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">qmake</span><span class="w"> </span><span class="o">-</span><span class="n">v</span>
<span class="n">QMake</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="mf">2.01</span><span class="n">a</span>
<span class="n">Using</span><span class="w"> </span><span class="n">Qt</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="mf">4.8</span><span class="o">.</span><span class="mi">6</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="o">/</span><span class="n">opt</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">homebrew</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">qt</span><span class="o">/</span><span class="mf">4.8</span><span class="o">.</span><span class="mi">6</span><span class="o">/</span><span class="n">lib</span>
<span class="o">$</span><span class="w"> </span><span class="n">qmake</span><span class="w"> </span><span class="o">-</span><span class="n">v</span>
<span class="n">QMake</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="mf">2.01</span><span class="n">a</span>
<span class="n">Using</span><span class="w"> </span><span class="n">Qt</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="mf">4.8</span><span class="o">.</span><span class="mi">6</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="o">/</span><span class="n">opt</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">homebrew</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">qt</span><span class="o">/</span><span class="mf">4.8</span><span class="o">.</span><span class="mi">6</span><span class="o">/</span><span class="n">lib</span>
</code></pre></div>
<p>哈哈!!!上百M 的怪物哪...</p>
<h3 id="qt">手编 Qt<a class="headerlink" href="#qt" title="Permanent link">¶</a></h3>
<ul>
<li><a href="http://amjith.blogspot.com/2010/09/developing-pyqt4-applications-in-mac-os.html">Developing PyQt4 Applications in Mac OS X | Core Dump</a></li>
</ul>
<h2 id="150416-try-again">150416 try again<a class="headerlink" href="#150416-try-again" title="Permanent link">¶</a></h2>
<p>删除 /opt/bin/homebrew 的非常安装</p>
<div class="highlight"><pre><span></span><code><span class="o">$</span><span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">qt</span><span class="w"> </span><span class="n">sip</span><span class="w"> </span><span class="n">pyqt</span>
<span class="o">==></span><span class="w"> </span><span class="n">Downloading</span><span class="w"> </span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">homebrew</span><span class="o">.</span><span class="n">bintray</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">bottles</span><span class="o">/</span><span class="n">qt</span><span class="o">-</span><span class="mf">4.8</span><span class="o">.</span><span class="mf">6.</span><span class="n">yosemite</span><span class="o">.</span><span class="n">bottle</span><span class="o">.</span><span class="mf">6.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
<span class="c1">######################################################################## 100.0%</span>
<span class="o">==></span><span class="w"> </span><span class="n">Pouring</span><span class="w"> </span><span class="n">qt</span><span class="o">-</span><span class="mf">4.8</span><span class="o">.</span><span class="mf">6.</span><span class="n">yosemite</span><span class="o">.</span><span class="n">bottle</span><span class="o">.</span><span class="mf">6.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
<span class="o">==></span><span class="w"> </span><span class="n">Caveats</span>
<span class="n">We</span><span class="w"> </span><span class="n">agreed</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">Qt</span><span class="w"> </span><span class="n">opensource</span><span class="w"> </span><span class="n">license</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">you</span><span class="o">.</span>
<span class="n">If</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">unacceptable</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">should</span><span class="w"> </span><span class="n">uninstall</span><span class="o">.</span>
<span class="o">.</span><span class="n">app</span><span class="w"> </span><span class="n">bundles</span><span class="w"> </span><span class="n">were</span><span class="w"> </span><span class="n">installed</span><span class="o">.</span>
<span class="n">Run</span><span class="w"> </span><span class="err">`</span><span class="n">brew</span><span class="w"> </span><span class="n">linkapps</span><span class="w"> </span><span class="n">qt</span><span class="err">`</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">symlink</span><span class="w"> </span><span class="n">these</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="o">/</span><span class="n">Applications</span><span class="o">.</span>
<span class="o">==></span><span class="w"> </span><span class="n">Summary</span>
<span class="err">🍺</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">qt</span><span class="o">/</span><span class="mf">4.8</span><span class="o">.</span><span class="mi">6</span><span class="p">:</span><span class="w"> </span><span class="mi">2790</span><span class="w"> </span><span class="n">files</span><span class="p">,</span><span class="w"> </span><span class="mi">122</span><span class="n">M</span>
</code></pre></div>
<p>...</p>
<div class="highlight"><pre><span></span><code><span class="o">==></span><span class="w"> </span><span class="o">./</span><span class="n">configure</span><span class="w"> </span><span class="o">--</span><span class="n">prefix</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">python</span><span class="o">/</span><span class="mf">2.7</span><span class="o">.</span><span class="mi">9</span><span class="w"> </span><span class="o">--</span><span class="n">enable</span><span class="o">-</span><span class="n">ipv6</span><span class="w"> </span><span class="o">--</span><span class="n">datarootdir</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">pyth</span>
<span class="o">==></span><span class="w"> </span><span class="n">make</span>
<span class="o">==></span><span class="w"> </span><span class="n">make</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">PYTHONAPPSDIR</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">python</span><span class="o">/</span><span class="mf">2.7</span><span class="o">.</span><span class="mi">9</span>
<span class="o">==></span><span class="w"> </span><span class="n">make</span><span class="w"> </span><span class="n">frameworkinstallextras</span><span class="w"> </span><span class="n">PYTHONAPPSDIR</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">python</span><span class="o">/</span><span class="mf">2.7</span><span class="o">.</span><span class="mi">9</span><span class="o">/</span><span class="n">share</span><span class="o">/</span><span class="n">python</span>
<span class="o">==></span><span class="w"> </span><span class="n">Downloading</span><span class="w"> </span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">pypi</span><span class="o">.</span><span class="n">python</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">packages</span><span class="o">/</span><span class="n">source</span><span class="o">/</span><span class="n">s</span><span class="o">/</span><span class="n">setuptools</span><span class="o">/</span><span class="n">setuptools</span><span class="o">-</span><span class="mf">15.0</span><span class="o">.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
<span class="c1">######################################################################## 100.0%</span>
<span class="o">==></span><span class="w"> </span><span class="n">Downloading</span><span class="w"> </span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">pypi</span><span class="o">.</span><span class="n">python</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">packages</span><span class="o">/</span><span class="n">source</span><span class="o">/</span><span class="n">p</span><span class="o">/</span><span class="n">pip</span><span class="o">/</span><span class="n">pip</span><span class="o">-</span><span class="mf">6.1</span><span class="o">.</span><span class="mf">0.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
<span class="c1">######################################################################## 100.0%</span>
<span class="o">==></span><span class="w"> </span><span class="n">Caveats</span>
<span class="n">Pip</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">setuptools</span><span class="w"> </span><span class="n">have</span><span class="w"> </span><span class="n">been</span><span class="w"> </span><span class="n">installed</span><span class="o">.</span><span class="w"> </span><span class="n">To</span><span class="w"> </span><span class="n">update</span><span class="w"> </span><span class="n">them</span>
<span class="w"> </span><span class="n">pip</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="o">--</span><span class="n">upgrade</span><span class="w"> </span><span class="n">pip</span><span class="w"> </span><span class="n">setuptools</span>
<span class="n">You</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">Python</span><span class="w"> </span><span class="n">packages</span><span class="w"> </span><span class="n">with</span>
<span class="w"> </span><span class="n">pip</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="o"><</span><span class="n">package</span><span class="o">></span>
<span class="n">They</span><span class="w"> </span><span class="n">will</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">into</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">site</span><span class="o">-</span><span class="n">package</span><span class="w"> </span><span class="n">directory</span>
<span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">python2</span><span class="o">.</span><span class="mi">7</span><span class="o">/</span><span class="n">site</span><span class="o">-</span><span class="n">packages</span>
<span class="n">See</span><span class="p">:</span><span class="w"> </span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">Homebrew</span><span class="o">/</span><span class="n">homebrew</span><span class="o">/</span><span class="n">blob</span><span class="o">/</span><span class="k">master</span><span class="o">/</span><span class="n">share</span><span class="o">/</span><span class="n">doc</span><span class="o">/</span><span class="n">homebrew</span><span class="o">/</span><span class="n">Homebrew</span><span class="o">-</span><span class="ow">and</span><span class="o">-</span><span class="n">Python</span><span class="o">.</span><span class="n">md</span>
<span class="o">.</span><span class="n">app</span><span class="w"> </span><span class="n">bundles</span><span class="w"> </span><span class="n">were</span><span class="w"> </span><span class="n">installed</span><span class="o">.</span>
<span class="n">Run</span><span class="w"> </span><span class="err">`</span><span class="n">brew</span><span class="w"> </span><span class="n">linkapps</span><span class="w"> </span><span class="n">python</span><span class="err">`</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">symlink</span><span class="w"> </span><span class="n">these</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="o">/</span><span class="n">Applications</span><span class="o">.</span>
<span class="o">...</span>
<span class="o">==></span><span class="w"> </span><span class="n">Pouring</span><span class="w"> </span><span class="n">sip</span><span class="o">-</span><span class="mf">4.16</span><span class="o">.</span><span class="mf">5.</span><span class="n">yosemite</span><span class="o">.</span><span class="n">bottle</span><span class="o">.</span><span class="mf">1.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
<span class="n">Traceback</span><span class="w"> </span><span class="p">(</span><span class="n">most</span><span class="w"> </span><span class="n">recent</span><span class="w"> </span><span class="n">call</span><span class="w"> </span><span class="n">last</span><span class="p">):</span>
<span class="w"> </span><span class="n">File</span><span class="w"> </span><span class="s2">"<string>"</span><span class="p">,</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="n">AttributeError</span><span class="p">:</span><span class="w"> </span><span class="s1">'module'</span><span class="w"> </span><span class="n">object</span><span class="w"> </span><span class="n">has</span><span class="w"> </span><span class="n">no</span><span class="w"> </span><span class="n">attribute</span><span class="w"> </span><span class="s1">'getusersitepackages'</span>
<span class="n">Traceback</span><span class="w"> </span><span class="p">(</span><span class="n">most</span><span class="w"> </span><span class="n">recent</span><span class="w"> </span><span class="n">call</span><span class="w"> </span><span class="n">last</span><span class="p">):</span>
<span class="w"> </span><span class="n">File</span><span class="w"> </span><span class="s2">"<string>"</span><span class="p">,</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="n">AttributeError</span><span class="p">:</span><span class="w"> </span><span class="s1">'module'</span><span class="w"> </span><span class="n">object</span><span class="w"> </span><span class="n">has</span><span class="w"> </span><span class="n">no</span><span class="w"> </span><span class="n">attribute</span><span class="w"> </span><span class="s1">'getusersitepackages'</span>
<span class="o">==></span><span class="w"> </span><span class="n">Caveats</span>
<span class="n">The</span><span class="w"> </span><span class="n">sip</span><span class="o">-</span><span class="n">dir</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">Python</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">share</span><span class="o">/</span><span class="n">sip</span><span class="o">.</span>
<span class="n">Python</span><span class="w"> </span><span class="n">modules</span><span class="w"> </span><span class="n">have</span><span class="w"> </span><span class="n">been</span><span class="w"> </span><span class="n">installed</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">Homebrew</span><span class="s1">'s site-packages is not</span>
<span class="ow">in</span><span class="w"> </span><span class="n">your</span><span class="w"> </span><span class="n">Python</span><span class="w"> </span><span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="p">,</span><span class="w"> </span><span class="n">so</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">will</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">able</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">import</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">modules</span>
<span class="n">this</span><span class="w"> </span><span class="n">formula</span><span class="w"> </span><span class="n">installed</span><span class="o">.</span><span class="w"> </span><span class="n">If</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">plan</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">develop</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">these</span><span class="w"> </span><span class="n">modules</span><span class="p">,</span>
<span class="n">please</span><span class="w"> </span><span class="n">run</span><span class="p">:</span>
<span class="w"> </span><span class="n">mkdir</span><span class="w"> </span><span class="o">-</span><span class="n">p</span>
<span class="w"> </span><span class="n">echo</span><span class="w"> </span><span class="s1">'import site; site.addsitedir("/usr/local/lib/python2.7/site-packages")'</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="n">homebrew</span><span class="o">.</span><span class="n">pth</span>
<span class="o">==></span><span class="w"> </span><span class="n">Summary</span>
<span class="err">🍺</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">sip</span><span class="o">/</span><span class="mf">4.16</span><span class="o">.</span><span class="mi">5</span><span class="p">:</span><span class="w"> </span><span class="mi">10</span><span class="w"> </span><span class="n">files</span><span class="p">,</span><span class="w"> </span><span class="mi">864</span><span class="n">K</span>
<span class="o">...</span>
<span class="o">==></span><span class="w"> </span><span class="n">Pouring</span><span class="w"> </span><span class="n">pyqt</span><span class="o">-</span><span class="mf">4.11</span><span class="o">.</span><span class="mf">3.</span><span class="n">yosemite</span><span class="o">.</span><span class="n">bottle</span><span class="o">.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
<span class="n">Traceback</span><span class="w"> </span><span class="p">(</span><span class="n">most</span><span class="w"> </span><span class="n">recent</span><span class="w"> </span><span class="n">call</span><span class="w"> </span><span class="n">last</span><span class="p">):</span>
<span class="w"> </span><span class="n">File</span><span class="w"> </span><span class="s2">"<string>"</span><span class="p">,</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="n">AttributeError</span><span class="p">:</span><span class="w"> </span><span class="s1">'module'</span><span class="w"> </span><span class="n">object</span><span class="w"> </span><span class="n">has</span><span class="w"> </span><span class="n">no</span><span class="w"> </span><span class="n">attribute</span><span class="w"> </span><span class="s1">'getusersitepackages'</span>
<span class="n">Traceback</span><span class="w"> </span><span class="p">(</span><span class="n">most</span><span class="w"> </span><span class="n">recent</span><span class="w"> </span><span class="n">call</span><span class="w"> </span><span class="n">last</span><span class="p">):</span>
<span class="w"> </span><span class="n">File</span><span class="w"> </span><span class="s2">"<string>"</span><span class="p">,</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="n">AttributeError</span><span class="p">:</span><span class="w"> </span><span class="s1">'module'</span><span class="w"> </span><span class="n">object</span><span class="w"> </span><span class="n">has</span><span class="w"> </span><span class="n">no</span><span class="w"> </span><span class="n">attribute</span><span class="w"> </span><span class="s1">'getusersitepackages'</span>
<span class="o">==></span><span class="w"> </span><span class="n">Caveats</span>
<span class="n">Phonon</span><span class="w"> </span><span class="n">support</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">broken</span><span class="o">.</span>
<span class="n">Python</span><span class="w"> </span><span class="n">modules</span><span class="w"> </span><span class="n">have</span><span class="w"> </span><span class="n">been</span><span class="w"> </span><span class="n">installed</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">Homebrew</span><span class="s1">'s site-packages is not</span>
<span class="ow">in</span><span class="w"> </span><span class="n">your</span><span class="w"> </span><span class="n">Python</span><span class="w"> </span><span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="p">,</span><span class="w"> </span><span class="n">so</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">will</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">able</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">import</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">modules</span>
<span class="n">this</span><span class="w"> </span><span class="n">formula</span><span class="w"> </span><span class="n">installed</span><span class="o">.</span><span class="w"> </span><span class="n">If</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">plan</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">develop</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">these</span><span class="w"> </span><span class="n">modules</span><span class="p">,</span>
<span class="n">please</span><span class="w"> </span><span class="n">run</span><span class="p">:</span>
<span class="w"> </span><span class="n">mkdir</span><span class="w"> </span><span class="o">-</span><span class="n">p</span>
<span class="w"> </span><span class="n">echo</span><span class="w"> </span><span class="s1">'import site; site.addsitedir("/usr/local/lib/python2.7/site-packages")'</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="n">homebrew</span><span class="o">.</span><span class="n">pth</span>
<span class="o">==></span><span class="w"> </span><span class="n">Summary</span>
<span class="err">🍺</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">pyqt</span><span class="o">/</span><span class="mf">4.11</span><span class="o">.</span><span class="mi">3</span><span class="p">:</span><span class="w"> </span><span class="mi">560</span><span class="w"> </span><span class="n">files</span><span class="p">,</span><span class="w"> </span><span class="mi">19</span><span class="n">M</span>
</code></pre></div>
<h1 id="_5">回顾<a class="headerlink" href="#_5" title="Permanent link">¶</a></h1>
<p>宏观上没有想象的复杂,因为真心作到了零配置!
几乎所有非第三方的配置,都继承了下来不用折腾!</p>
<p>唯三的折腾:</p>
<ol>
<li>Python 环境</li>
<li>Qt 环境</li>
<li>sshfs</li>
</ol>
<p>严正推荐:</p>
<p><a href="file:///Users/zoomq/mnt/%E5%BF%AB%E7%9B%98/zScrapBook/ZqFLOSS/data/20131230190257/index.html">Mavericksでbrew upgradeしたらハマった話</a></p>
<p>等等日文的相关纪要非常实在,直觉,顺序合理,值得,多参考.</p>
<h2 id="python-qt-for-leo">Python + Qt for Leo<a class="headerlink" href="#python-qt-for-leo" title="Permanent link">¶</a></h2>
<p>大家知道俺是 <a href="http://wiki.woodpecker.org.cn/moin/LiterateProgramming">文学化编程</a>
的拥趸,
所以,一直使用 <a href="http://wiki.woodpecker.org.cn/moin/LeoEnvironment">Leo</a>
作为主要编程环境的,</p>
<p>10.9 以后 Python 不内置安装了,
Qt 当然从来也没有内置过.
所以,</p>
<h3 id="python">Python<a class="headerlink" href="#python" title="Permanent link">¶</a></h3>
<p>当然,系统的用 <code>brew install python</code> 了,</p>
<p>而其它各种项目开发时,就要综合使用</p>
<h4 id="pyenvvirtualenv">Pyenv+VirtualEnv<a class="headerlink" href="#pyenvvirtualenv" title="Permanent link">¶</a></h4>
<p>Pyenv 是这样一种神器:</p>
<p>完全的面向shell
通过环境变量的自动配置
形成复合Python版本共存</p>
<p>VirtualEnv 有 Pyenv 的插件
所以,可以利用已安装好的环境,快速复制出项目专用的,
结果,引发了滥用,特别舒服的那种:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>pyenv<span class="w"> </span>versions
*<span class="w"> </span>system<span class="w"> </span><span class="o">(</span><span class="nb">set</span><span class="w"> </span>by<span class="w"> </span>/Users/zoomq/.pyenv/version<span class="o">)</span>
<span class="w"> </span><span class="m">2</span>.7.3
<span class="w"> </span><span class="m">2</span>.7.5
<span class="w"> </span><span class="m">2</span>.7.6
<span class="w"> </span>273SAE
<span class="w"> </span>275lbTC
<span class="w"> </span>275pelican
<span class="w"> </span>276SphinxOBP
<span class="w"> </span>276chaos
<span class="w"> </span>276uliweb
<span class="w"> </span><span class="m">3</span>.2
<span class="w"> </span><span class="m">3</span>.3.2
<span class="w"> </span>32IPy
<span class="w"> </span>ipynotebook
<span class="w"> </span>pypy-2.2.1
<span class="w"> </span>pypy221chaos
</code></pre></div>
<p>主要遇到的问题是:</p>
<div class="highlight"><pre><span></span><code><span class="o">==></span><span class="w"> </span><span class="n">Installing</span><span class="w"> </span><span class="n">python3</span>
<span class="o">==></span><span class="w"> </span><span class="n">Downloading</span><span class="w"> </span><span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">python</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">ftp</span><span class="o">/</span><span class="n">python</span><span class="o">/</span><span class="mf">3.3</span><span class="o">.</span><span class="mi">3</span><span class="o">/</span><span class="n">Python</span><span class="o">-</span><span class="mf">3.3</span><span class="o">.</span><span class="mf">3.</span><span class="n">tar</span><span class="o">.</span><span class="n">bz2</span>
<span class="c1">######################################################################## 100.0%</span>
<span class="o">==></span><span class="w"> </span><span class="o">./</span><span class="n">configure</span><span class="w"> </span><span class="o">--</span><span class="n">prefix</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">python3</span><span class="o">/</span><span class="mf">3.3</span><span class="o">.</span><span class="mi">3</span><span class="w"> </span><span class="o">--</span><span class="n">enable</span><span class="o">-</span><span class="n">ipv6</span><span class="w"> </span><span class="o">--</span><span class="n">datarootdir</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">python3</span><span class="o">/</span><span class="mf">3.3</span><span class="o">.</span><span class="mi">3</span><span class="o">/</span><span class="n">share</span><span class="w"> </span><span class="o">--</span><span class="n">datadir</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">lo</span>
<span class="o">==></span><span class="w"> </span><span class="n">make</span>
<span class="o">==></span><span class="w"> </span><span class="n">make</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">PYTHONAPPSDIR</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">python3</span><span class="o">/</span><span class="mf">3.3</span><span class="o">.</span><span class="mi">3</span>
<span class="o">==></span><span class="w"> </span><span class="n">make</span><span class="w"> </span><span class="n">frameworkinstallextras</span><span class="w"> </span><span class="n">PYTHONAPPSDIR</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">python3</span><span class="o">/</span><span class="mf">3.3</span><span class="o">.</span><span class="mi">3</span><span class="o">/</span><span class="n">share</span><span class="o">/</span><span class="n">python3</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
</code></pre></div>
<p>指定具体版本,尝试,直到可以顺利安装出可用的就好.</p>
<p>严正表扬一下 'Yamashita, Yuu`</p>
<ul>
<li><a href="https://github.com/yyuu/pyenv/issues/95#issuecomment-31392999">How to config pyenv's pip ? · Issue #95 · yyuu/pyenv</a></li>
<li>绝对认真的回答了俺的提问,虽然不了了之,但是,一个常用工具的作者,可以如此关注一个不是问题的问题,实在太勤勉了,必须学习!</li>
</ul>
<h3 id="qt-for-leo">Qt for Leo<a class="headerlink" href="#qt-for-leo" title="Permanent link">¶</a></h3>
<p>参考:</p>
<ul>
<li><a href="http://support.apple.com/kb/HT5293">About X11 and OS X</a></li>
<li><a href="http://xquartz.macosforge.org/landing/">XQuartz</a></li>
</ul>
<p>以及:</p>
<div class="highlight"><pre><span></span><code><span class="o">$</span><span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">pyqt</span>
<span class="o">==></span><span class="w"> </span><span class="n">Downloading</span><span class="w"> </span><span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">downloads</span><span class="o">.</span><span class="n">sf</span><span class="o">.</span><span class="n">net</span><span class="o">/</span><span class="n">project</span><span class="o">/</span><span class="n">pyqt</span><span class="o">/</span><span class="n">PyQt4</span><span class="o">/</span><span class="n">PyQt</span><span class="o">-</span><span class="mf">4.10</span><span class="o">.</span><span class="mi">3</span><span class="o">/</span><span class="n">PyQt</span><span class="o">-</span><span class="n">mac</span><span class="o">-</span><span class="n">gpl</span><span class="o">-</span><span class="mf">4.10</span><span class="o">.</span><span class="mf">3.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
<span class="n">Already</span><span class="w"> </span><span class="n">downloaded</span><span class="p">:</span><span class="w"> </span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Caches</span><span class="o">/</span><span class="n">Homebrew</span><span class="o">/</span><span class="n">pyqt</span><span class="o">-</span><span class="mf">4.10</span><span class="o">.</span><span class="mf">3.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
<span class="o">==></span><span class="w"> </span><span class="n">Patching</span>
<span class="n">patching</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">configure</span><span class="o">.</span><span class="n">py</span>
<span class="o">==></span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">opt</span><span class="o">/</span><span class="n">python</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">python2</span><span class="w"> </span><span class="n">configure</span><span class="o">.</span><span class="n">py</span><span class="w"> </span><span class="o">--</span><span class="n">confirm</span><span class="o">-</span><span class="n">license</span><span class="w"> </span><span class="o">--</span><span class="n">bindir</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">pyqt</span><span class="o">/</span><span class="mf">4.10</span><span class="o">.</span><span class="mi">3</span><span class="o">/</span><span class="n">bin</span><span class="w"> </span><span class="o">--</span><span class="n">destdir</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span>
<span class="n">Error</span><span class="p">:</span><span class="w"> </span><span class="n">Unable</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">find</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">qmake</span><span class="w"> </span><span class="n">configuration</span><span class="w"> </span><span class="n">file</span>
<span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">qt</span><span class="o">/</span><span class="mf">4.8</span><span class="o">.</span><span class="mi">5</span><span class="o">/</span><span class="n">mkspecs</span><span class="o">/</span><span class="n">unsupported</span><span class="o">/</span><span class="n">macx</span><span class="o">-</span><span class="n">clang</span><span class="o">-</span><span class="n">libc</span><span class="o">++/</span><span class="n">qmake</span><span class="o">.</span><span class="n">conf</span><span class="o">.</span>
<span class="n">Use</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">QMAKESPEC</span><span class="w"> </span><span class="n">environment</span><span class="w"> </span><span class="n">variable</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">specify</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">correct</span><span class="w"> </span><span class="n">platform</span><span class="o">.</span>
<span class="n">Determining</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">layout</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">your</span><span class="w"> </span><span class="n">Qt</span><span class="w"> </span><span class="n">installation</span><span class="o">...</span>
<span class="n">READ</span><span class="w"> </span><span class="n">THIS</span><span class="p">:</span><span class="w"> </span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">Homebrew</span><span class="o">/</span><span class="n">homebrew</span><span class="o">/</span><span class="n">wiki</span><span class="o">/</span><span class="n">troubleshooting</span>
</code></pre></div>
<p>多多 Google 吧,很标准的环境驱动, Qt 官方提供了的,</p>
<p>然后, Leo 只是一堆 Py 脚本下载下来,
修订一下别名指向就好:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># ~/.bashrc for running Leo</span>
<span class="nb">alias</span><span class="w"> </span><span class="nv">leolanch</span><span class="o">=</span><span class="s2">"python /opt/bin/leo/launchLeo.py >> /dev/null 2>&1 &"</span>
</code></pre></div>
<h2 id="sshfs">伟光大的 sshfs<a class="headerlink" href="#sshfs" title="Permanent link">¶</a></h2>
<div class="highlight"><pre><span></span><code><span class="o">$</span><span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">link</span><span class="w"> </span><span class="n">fuse4x</span>
<span class="n">Linking</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">fuse4x</span><span class="o">/</span><span class="mf">0.9</span><span class="o">.</span><span class="mf">2.</span><span class="o">..</span><span class="w"> </span><span class="n">Warning</span><span class="p">:</span><span class="w"> </span><span class="n">Could</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="n">link</span><span class="w"> </span><span class="n">fuse4x</span><span class="o">.</span><span class="w"> </span><span class="n">Unlinking</span><span class="o">...</span>
<span class="n">Error</span><span class="p">:</span><span class="w"> </span><span class="n">Could</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="n">symlink</span><span class="w"> </span><span class="n">file</span><span class="p">:</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">fuse4x</span><span class="o">/</span><span class="mf">0.9</span><span class="o">.</span><span class="mi">2</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">pkgconfig</span><span class="o">/</span><span class="n">fuse</span><span class="o">.</span><span class="n">pc</span>
<span class="n">Target</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">pkgconfig</span><span class="o">/</span><span class="n">fuse</span><span class="o">.</span><span class="n">pc</span><span class="w"> </span><span class="n">already</span><span class="w"> </span><span class="n">exists</span><span class="o">.</span><span class="w"> </span><span class="n">You</span><span class="w"> </span><span class="n">may</span><span class="w"> </span><span class="n">need</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">delete</span><span class="w"> </span><span class="n">it</span><span class="o">.</span>
<span class="n">To</span><span class="w"> </span><span class="n">force</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">link</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">overwrite</span><span class="w"> </span><span class="n">all</span><span class="w"> </span><span class="n">other</span><span class="w"> </span><span class="n">conflicting</span><span class="w"> </span><span class="n">files</span><span class="p">,</span><span class="w"> </span><span class="n">do</span><span class="p">:</span>
<span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">link</span><span class="w"> </span><span class="o">--</span><span class="n">overwrite</span><span class="w"> </span><span class="n">formula_name</span>
<span class="n">To</span><span class="w"> </span><span class="n">list</span><span class="w"> </span><span class="n">all</span><span class="w"> </span><span class="n">files</span><span class="w"> </span><span class="n">that</span><span class="w"> </span><span class="n">would</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">deleted</span><span class="p">:</span>
<span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">link</span><span class="w"> </span><span class="o">--</span><span class="n">overwrite</span><span class="w"> </span><span class="o">--</span><span class="n">dry</span><span class="o">-</span><span class="n">run</span><span class="w"> </span><span class="n">formula_name</span>
<span class="n">zoomq</span><span class="w"> </span><span class="err">@</span><span class="w"> </span><span class="n">MBP111216ZQ</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">lib</span>
<span class="o">$</span><span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">link</span><span class="w"> </span><span class="o">--</span><span class="n">overwrite</span><span class="w"> </span><span class="n">fuse4x</span>
<span class="n">Linking</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">fuse4x</span><span class="o">/</span><span class="mf">0.9</span><span class="o">.</span><span class="mf">2.</span><span class="o">..</span><span class="w"> </span><span class="mi">7</span><span class="w"> </span><span class="n">symlinks</span><span class="w"> </span><span class="n">created</span>
<span class="o">$</span><span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">osxfuse</span>
<span class="o">==></span><span class="w"> </span><span class="n">Downloading</span><span class="w"> </span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">downloads</span><span class="o">.</span><span class="n">sf</span><span class="o">.</span><span class="n">net</span><span class="o">/</span><span class="n">project</span><span class="o">/</span><span class="n">machomebrew</span><span class="o">/</span><span class="n">Bottles</span><span class="o">/</span><span class="n">osxfuse</span><span class="o">-</span><span class="mf">2.6</span><span class="o">.</span><span class="mf">2.</span><span class="n">mavericks</span><span class="o">.</span><span class="n">bottle</span><span class="o">.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
<span class="o">==></span><span class="w"> </span><span class="n">Pouring</span><span class="w"> </span><span class="n">osxfuse</span><span class="o">-</span><span class="mf">2.6</span><span class="o">.</span><span class="mf">2.</span><span class="n">mavericks</span><span class="o">.</span><span class="n">bottle</span><span class="o">.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
<span class="o">==></span><span class="w"> </span><span class="n">Caveats</span>
<span class="n">If</span><span class="w"> </span><span class="n">upgrading</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">previous</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">osxfuse</span><span class="p">,</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">previous</span><span class="w"> </span><span class="n">kernel</span><span class="w"> </span><span class="n">extension</span>
<span class="n">will</span><span class="w"> </span><span class="n">need</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">unloaded</span><span class="w"> </span><span class="n">before</span><span class="w"> </span><span class="n">installing</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">new</span><span class="w"> </span><span class="n">version</span><span class="o">.</span><span class="w"> </span><span class="n">First</span><span class="p">,</span><span class="w"> </span><span class="n">check</span><span class="w"> </span><span class="n">that</span>
<span class="n">no</span><span class="w"> </span><span class="n">FUSE</span><span class="o">-</span><span class="n">based</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">systems</span><span class="w"> </span><span class="n">are</span><span class="w"> </span><span class="n">running</span><span class="p">:</span>
<span class="w"> </span><span class="n">mount</span><span class="w"> </span><span class="o">-</span><span class="n">t</span><span class="w"> </span><span class="n">osxfusefs</span>
<span class="n">Unmount</span><span class="w"> </span><span class="n">all</span><span class="w"> </span><span class="n">FUSE</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">systems</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">then</span><span class="w"> </span><span class="n">unload</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">kernel</span><span class="w"> </span><span class="n">extension</span><span class="p">:</span>
<span class="w"> </span><span class="n">sudo</span><span class="w"> </span><span class="n">kextunload</span><span class="w"> </span><span class="o">-</span><span class="n">b</span><span class="w"> </span><span class="n">com</span><span class="o">.</span><span class="n">github</span><span class="o">.</span><span class="n">osxfuse</span><span class="o">.</span><span class="n">filesystems</span><span class="o">.</span><span class="n">osxfusefs</span>
<span class="n">The</span><span class="w"> </span><span class="n">new</span><span class="w"> </span><span class="n">osxfuse</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">system</span><span class="w"> </span><span class="n">bundle</span><span class="w"> </span><span class="n">needs</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">installed</span><span class="w"> </span><span class="n">by</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">root</span><span class="w"> </span><span class="n">user</span><span class="p">:</span>
<span class="w"> </span><span class="n">sudo</span><span class="w"> </span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">cp</span><span class="w"> </span><span class="o">-</span><span class="n">RfX</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">osxfuse</span><span class="o">/</span><span class="mf">2.6</span><span class="o">.</span><span class="mi">2</span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Filesystems</span><span class="o">/</span><span class="n">osxfusefs</span><span class="o">.</span><span class="n">fs</span><span class="w"> </span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Filesystems</span>
<span class="w"> </span><span class="n">sudo</span><span class="w"> </span><span class="n">chmod</span><span class="w"> </span><span class="o">+</span><span class="n">s</span><span class="w"> </span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Filesystems</span><span class="o">/</span><span class="n">osxfusefs</span><span class="o">.</span><span class="n">fs</span><span class="o">/</span><span class="n">Support</span><span class="o">/</span><span class="n">load_osxfusefs</span>
<span class="o">==></span><span class="w"> </span><span class="n">Summary</span>
<span class="err">🍺</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">osxfuse</span><span class="o">/</span><span class="mf">2.6</span><span class="o">.</span><span class="mi">2</span><span class="p">:</span><span class="w"> </span><span class="mi">84</span><span class="w"> </span><span class="n">files</span><span class="p">,</span><span class="w"> </span><span class="mf">5.0</span><span class="n">M</span>
</code></pre></div>
<p>具体哪个管用,俺也没整明白,
反正,怎么折腾,
都是可以正当加载上 <code>Plan</code> 的内核库,
然后就可以对家庭服务器的所有硬盘,远程加载为本地目录了..</p>
<h1 id="changelog">Changelog<a class="headerlink" href="#changelog" title="Permanent link">¶</a></h1>
<ul>
<li>160419 增补后来的折腾</li>
<li>140616 再次精简,算是发布</li>
<li>140505 快速简述完成</li>
<li>140110 起意,总结</li>
</ul>再见了 Python2015-01-10T00:00:00+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2015-01-10:/saying-ggodby-python-zh.html<p>原文: <a href="http://www.ianbicking.org/blog/2014/02/saying-goodbye-to-python.html">Saying Goodbye To Python</a></p>
<p>This post is long overdue; this isn't a declaration of intent (any intent was long ago made real), just my reflection about my own path. I left the Python world a long time ago but I never took a chance to say goodbye.</p>
<p>While …</p><p>原文: <a href="http://www.ianbicking.org/blog/2014/02/saying-goodbye-to-python.html">Saying Goodbye To Python</a></p>
<p>This post is long overdue; this isn't a declaration of intent (any intent was long ago made real), just my reflection about my own path. I left the Python world a long time ago but I never took a chance to say goodbye.</p>
<p>While I had moved on from Python years ago, I felt a certain attachment to it well past then, not quite admitting to myself that I wasn't coming back. When my proposal for PyCon 2013 was rejected I was frustrated (it was going to be a fun talk!) but for some reason that made me fully realized that I wasn't part of the Python community anymore.</p>
<p>Python was the first — and I sometimes wonder if the only — programming community I was part of. Coming to Python was a conscious choice. In college I was interested in Scheme and Smalltalk. High-minded languages with interesting ideas, but hard to find practical uses. Scheme was always too underserved by its libraries and sparse academic community. In contrast Smalltalk was productive — it was built by and for people who loved to build things. (More credit here should probably go to Dan Ingalls than Alan Kay — I can sense in Dan Ingalls's work a real passion for making things, and a pure but unproductive language would not have satisfied him.) But Smalltalk was and is a world of its own. It was culturally and technically pre-internet, pre-open-source, pre-online-community. And despite all the great things about the Smalltalk environment and language it couldn't fulfill these then-new potentials, even as it tried to adapt. (I wrote a couple posts about this, intended as a sort of sympathetic explanation of why I couldn't stick with Smalltalk: Where Smalltalk Went Wrong and a followup.)</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Daniel_Henry_Holmes_Ingalls,_Jr.">Dan Ingalls</a></li>
<li><a href="http://en.wikipedia.org/wiki/Alan_Kay">Alan Kay</a></li>
<li><a href="http://www.ianbicking.org/where-smalltalk-went-wrong.html">Where Smalltalk Went Wrong</a></li>
<li><a href="http://www.ianbicking.org/where-smalltalk-went-wrong-2.html">a followup</a></li>
</ul>
<p>At the end of my college career (1999ish) I consciously looked for a new home. I flirted with Perl, C, but knew they weren't for me. Somewhere along the way I came upon Python, and it was good enough that I didn't look for anything better. I can't say I fell in love with Python like I had with Scheme and Smalltalk — Scheme was like an opening up of the world after going far beyond what anyone should ask of GW-BASIC, and Squeak/Smalltalk was a deep mysterious world, like coming upon the ruins of an ancient and advanced civilization. Python in comparison was practical — but I wasn't in the mood at that time to discover, I wanted to build.</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/GW-BASIC">GW - BASIC</a></li>
</ul>
<p>And I built a lot of things in Python. I was doing workaday web programming and my enthusiasm went more towards building tools to build stuff than in the building itself. I did build some cool products in those days, not just libraries, but for some reason it's only the smaller units that I was able to push out. And I found a community in Python.</p>
<ul>
<li><a href="http://www.ianbicking.org/projects.html">built a lot of things in Python</a></li>
</ul>
<p>And I built. Back in the days I contributed to Webware, what felt like a completely different generation of web development in Python than today. I wrote SQLObject, my first foray into a oh-shit-people-are-using-this-I'm-not-sure-how-I-feel-about-that library. But SQLObject explored a lot of metaprogramming concepts that were quite novel in the Python world at that time. At the same time maintaining it felt like a terrible burden. It took me far too long to resolve that, and only once interest had died down (in no small part due to my lack of attention) did I hand it over to Oleg who has been a far more steady hand. This would be a pattern I would unfortunately repeat. But if SQLObject helped the next generation be better that's good enough for me.</p>
<ul>
<li><a href="http://www.webwareforpython.org/">Webware</a></li>
<li><a href="http://sqlobject.org/">SQLObject</a></li>
<li><a href="http://phdru.name/">Oleg</a></li>
<li><a href="http://www.sqlalchemy.org/">next generation</a></li>
</ul>
<p>Later came WSGI which excited me with its subtly functional basis. I built a whole web framework toolkit (or a framework for building web frameworks?) in Paste. Few people really understood what I was trying to do with Paste — at times including me. Some people like Ben Bangert were able to see the principles underneath the code, and get them out into the world in the kind of usable state that I intended to enable. (And along the way I sometimes felt like I was doing the same for PJE.) Python web frameworks were a mess back then; ultimately reaching for the crown using a monolithic approach was a more successful technique than trying to build bridges as I attempted with Paste. I'm still not sure what lesson to take from that. Not a general lesson, but more understanding the landscape. And understanding what you can bring to a problem, and who you can bring with. I feel like I'm only now really understanding the importance of vision combined with a diverse group of skills and perspectives, and I have even more to learn about how to actually assemble and coordinate the right group of people in the right environment to succeed.</p>
<ul>
<li><a href="http://wsgi.readthedocs.org/">WSGI</a></li>
<li><a href="http://pythonpaste.org/">Paste</a></li>
<li><a href="http://groovie.org/">Ben Bangert</a></li>
<li><a href="https://www.djangoproject.com/">reaching for the crown</a></li>
</ul>
<p>Somewhere around here I feel like I reached my 10,000 hours of Python coding. I wrote WebOb, taking the lessons of Paste and a better intuition for library design. I still think it's the best mapping of HTTP to Python. Other libraries include more aspects of web development in their scope, or have better documentation, and more users, but when viewed with a particular lens I'm still very proud of WebOb. And it's been an important building block in a lot of people's explorations into building a web framework. Other libraries from this period are lxml.html, smaller things like WebTest, ScriptTest, MiniMock, Tempita, perhaps the over-ambition (or just mis-ambition) of Deliverance. That period felt like a clearing out of my system, unloading a bunch of ideas.</p>
<ul>
<li><a href="http://webob.org/">WebOb</a></li>
<li><a href="http://docs.webob.org/en/latest/do-it-yourself.html">building a web framework</a></li>
<li><a href="http://lxml.de/lxmlhtml.html">lxml.html</a></li>
<li><a href="http://webtest.pythonpaste.org/">WebTest</a></li>
<li><a href="http://pythonpaste.org/scripttest/">ScriptTest</a></li>
<li><a href="https://pypi.python.org/pypi/MiniMock">MiniMock</a></li>
<li><a href="http://pythonpaste.org/tempita/">Tempita</a></li>
<li><a href="http://www.coactivate.org/projects/deliverance/introduction">Deliverance</a></li>
</ul>
<p>But for whatever reason my most successful tools were virtualenv and pip. These were never my greatest passions, or even close. They were about: (a) fixing personal annoyances in deployment (virtualenv), and (b) getting people to stop fucking whining about Setuptools and easy_install (pip). I'm not sure whether I blame the uneasy success of these tools on broad appeal, or that they are in a sense user-visible tools and not libraries, or that I didn't like doing them because no one liked doing them and so there was a vacuum waiting to be filled.</p>
<ul>
<li><a href="http://www.virtualenv.org/">virtualenv</a></li>
<li><a href="http://www.pip-installer.org/">pip</a></li>
</ul>
<p>And then my last project, Silver Lining. It was early on in the devops revolution, an attempt to think about what a generic container for web applications might look like. It was in a sense going deeper down the hole of virtualenv and pip, but with an aim to build a full product and not just a set of eclectic tools. No one cared. And I only cared a little — I cared because it was completing some ideas I'd long had about deployment, because for a certain kind of web application development it felt nimble and reliable, because it removed or automated tasks I didn't like to do. But I didn't care, no more than I cared about virtualenv or pip. I'd gone down a path that was about code and technical design, but if I stepped back it was unexciting.</p>
<ul>
<li><a href="https://bitbucket.org/ianb/silverlining/src">Silver Lining</a></li>
</ul>
<p>And when I did step back there wasn't anything in Python that excited me. Python was doing great, my interest had nothing to jumping on or off bandwagons. Python is doing great — better than ever (minor bumps with versions aside). But I think in my mind I'd always imagined I could build up just the right toolset, and using that toolset create the product I actually wanted to create — what exactly that product was, I don't know, but with the right tools I imagined I could move fast enough and confidently enough to find it.</p>
<ul>
<li><a href="https://plus.google.com/+IanBicking/posts/iEVXdcfXkz7">minor bumps with versions aside</a></li>
</ul>
<p>Sometimes when I'm feeling particularly excited about an idea, like really excited, I have to take a break. I need to calm down. Try to wrap my head around the ideas, because I know if I push forward directly that I'll just muddle things up and feel disappointed. No, I don't know that is true: maybe I don't want to have to confront, in that moment, that the idea is not as cool as I think it is, or as possible as I think it is. But often I do step back into the problem, with ideas that are more mature for having thought more deeply about them. In a sense I think creating tools and libraries was a similar process: I felt too excited about creating something great, because I worried I'd muddle everything up, or afraid I just couldn't pull it off, and so I stepped away and would work on tools.</p>
<p>I always directed my attention to the web, even if I got bogged down in the server. Somehow I skipped native GUIs, even as a user. But pure data processing without consideration for what you do with the data felt unexciting. And ops — that's just the worst. I was, and am, a true believer in Free Software; and I was, and am, a true believer in the web. That is, I don't see either as simply a means to an ends. But not for the same reasons, and I can believe in a web that isn't open source, and open source that isn't for the web. And yet writing it down I realize I don't care about open source that isn't for the web.</p>
<p>When I stepped back Python no longer seemed relevant to the web, at least not the part of the web that interested me. The tools I had built were no longer relevant either, they were not the tools with which I could realize my ambitions. The database-backed website, or the dynamic-HTTP-based web application, templates and deployments, anything you'd call "REST" — none of it seemed like the future, and whatever this vague thing was that I'd been looking for, I wasn't going to find it there.</p>
<p>This wasn't an actual revelation, I'm constructing it in retrospect. If you'd asked me I would have agreed with this notion even years earlier, and it's not like I came up with some unique idea, if anything I would call it self-evident, don't we all know this is where the world is going? And so I started to look towards Javascript and the browser and the DOM.</p>
<p>Somewhat before this I also joined Mozilla. But it would be backwards to say that Mozilla induced this change in perspective, that it tempted me away from Python. In fact I would have had a much easier time of it if I had just stuck with doing Python backend stuff at Mozilla.</p>
<p>The last few years of transition have been a struggle. With Python and the server I knew what I was doing. I was good at it, I felt competent. I could construct an opinion with confidence about all kinds of design questions. I was respected and my opinion would be listened to. I'd put in my 10,000 hours, I had achieved mastery.</p>
<p>Moving to Javascript none of this was true, and most of it still isn't true. It might be easier to pull off this change if I was doing web development, surrounded with people making similar transitions, a little fish in the little pond of whatever group I was working with. But Mozilla is not that kind of environment. Which is okay — if I had felt confident it would only be because there was no one to correct me.</p>
<p>It's oddly common to see people talk about how a programmer can pick up something new in the matter of a few days or months. To find programmers that consider all that knowledge transferable (for instance). I don't know what to make of it — my less forgiving self thinks these people have never known what real mastery is. I don't think it takes another 10,000 hours to get mastery in a new language and environment... but it definitely takes some thousands of hours, some years of hard work. I only now feel like I'm getting close.</p>
<ul>
<li><a href="https://news.ycombinator.com/item?id=7204515">for instance</a></li>
</ul>
<p>Maybe it's my perspective on what mastery is. Deciding to do something and then doing it is good. It is not mastery. You have to pick the right problem to solve. You have to pick the right way to solve it. You need to know when to revise that plan, and understand the constraints that inform that revision. You need both large scale and small scale intuitions. And you need to be good enough at all the details of programming in that environment that you don't get overwhelmed with the "easy" stuff, so you have mental energy to spare on the big stuff. The jump from Python to Javascript isn't that big, the languages have a very similar shape. And the browser was already the environment focused on. And yet redeveloping my intuition for this new environment has taken time.</p>
<p>Sadly I'm not going to get back where I was, because Javascript is not Python. If there's a Javascript community I haven't found it, or it's at least not a single entity. There is no community that created Javascript like the Python community created Python. Python comes from the internet in a way Javascript does not; Javascript was built for the internet, but Python was built on the internet. And I do miss the Python community, you're good people.</p>
<p>But also whatever language partisanship I had is gone, and won't come back in the guise of a new favorite language. This shouldn't be confused with a disinterest in language. I still get as annoyed as ever by "use the right tool for the job" — the bland truism meant to shut down critical discussion and engagement with the tasks and choices in software engineering, replacing it with a weak passionless technical fatalism.</p>
<p>I suppose it is the platform that I am drawn to now before language. And the browser seems like the most interesting platform, not because it's novel (though it is, it's a runtime like few others), but because of how concrete it is, and of course how relevant it is to... anything. And the browser is no longer just the servant of a server, I prefer now to think of the browser as an independent agent, connecting to services instead of servers. Obviously that doesn't describe a great number of running web sites, but it's the model I see for the future, and a better perspective for understanding future architectures.</p>
<p>Still this only addresses which direction I'm looking towards, I still have to walk the path. I don't want to get caught up in the weeds again, building tools for something I never manage to make. Right now I think I'm on to something in the area of collaboration, first with TogetherJS and now I'm thinking bigger with a new experiment. But while I feel like I've reached some competence in executing on these projects, programming is only one piece of bringing forward a larger vision. I still have a lot of learning to do, skills for which I haven't put in the necessary time. How to recruit support, how to manage the project, how to negotiate between feasibility and user value, how to negotiate compromises in strategy and design. And collaboration itself is a whole domain of expertise. I've learned a lot, I can do things, but I am definitely not yet experienced enough to choose to do the right thing in these areas. And at this moment I'm worried I won't have the room to learn these things, it feels like time is running out just when I'm pulling stuff together.</p>
<ul>
<li><a href="https://togetherjs.com/">TogetherJS</a></li>
<li><a href="http://github.com/mozilla/hotdish">new experiment</a></li>
</ul>
<p>Anyway, that's where I am now. No longer a language partisan, unclear of what community I am even participating in, I am less sure how to identify and self-identify myself. How do I describe myself now? Even as I find my technical footing I am still adrift. And so it's hard to say goodbye. So instead I'll say, Pythonistas: until we meet again. Maybe I'll meet some of you over here.</p>
<h2 id="changelog">Changelog<a class="headerlink" href="#changelog" title="Permanent link">¶</a></h2>
<ul>
<li>161201 是也乎,( ̄▽ ̄)<ul>
<li>发现也没有必要逐字翻译</li>
<li>作者是位勤劳的 Pythonista, 创造了从 SQLObject 到 Silver Lining 等等一系列</li>
<li>不成功的模块/工具/工程</li>
<li>现在是 <code>TogetherJS</code> 发起人</li>
<li>之所以从 Python 转进 JS 世界,只是因为感觉在 Python 中无论折腾什么都会进入混乱的竞争</li>
<li>细思恐极...</li>
</ul>
</li>
<li>150112 整理到个人 blog</li>
<li>150110 从周刊中发现,决定翻译</li>
</ul>如何将 ipynb 发布到 blog 中?2014-11-27T00:00:00+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2014-11-27:/141127-ipynb-into-blog.html<p>原文: <a href="http://prooffreaderplus.blogspot.ca/2014/11/how-to-quickly-turn-ipython-notebook.html">prooffreader plus: How to quickly turn an IPython notebook into a blog post</a></p>
<p>IPython notebooks are great for many things, but they're a little awkward to embed in blog post platforms like Blogger, Wordpress, etc. When the nbconvert feature was a standalone command-line tool, there was a blog …</p><p>原文: <a href="http://prooffreaderplus.blogspot.ca/2014/11/how-to-quickly-turn-ipython-notebook.html">prooffreader plus: How to quickly turn an IPython notebook into a blog post</a></p>
<p>IPython notebooks are great for many things, but they're a little awkward to embed in blog post platforms like Blogger, Wordpress, etc. When the nbconvert feature was a standalone command-line tool, there was a blog export template, but that seems to have disappeared now that nbconvert has been folded within IPython.</p>
<p>Out of the box, nbconvert just has two html export options:</p>
<div class="highlight"><pre><span></span><code>--html
</code></pre></div>
<p>which includes a lot of CSS that interferes with a blog's CSS, and:</p>
<div class="highlight"><pre><span></span><code>--html --template basic
</code></pre></div>
<p>which has no CSS and so pretty much negates the benefit of using an IPython notebook. However, it does have CSS classess in the text.</p>
<p>My solution was to whip up a quick CSS stylesheet that could be included in the blog post. It seems to work pretty well; you can have a look at:</p>
<ul>
<li>an <a href="http://nbviewer.ipython.org/github/Prooffreader/Misc_ipynb/blob/master/top_10_python_idioms.ipynb">IPython notebook in nbviewer</a> of a recent blog post of mine</li>
<li>the <a href="http://prooffreaderplus.blogspot.ca/2014/11/top-10-python-idioms-i-wished-id.html">blog version</a> after applying this stylesheet.</li>
</ul>
<p>Note that, for aesthetic reasons, I removed all the</p>
<div class="highlight"><pre><span></span><code>In [1]
</code></pre></div>
<p>-style tags because of the narrow columns on this blog. Your mileage may vary.</p>
<h2 id="1-convert-ipynb-notebook-to-html">1. Convert .ipynb notebook to HTML<a class="headerlink" href="#1-convert-ipynb-notebook-to-html" title="Permanent link">¶</a></h2>
<p>In the terminal, navigate to the folder containing the .ipynb file and type:</p>
<div class="highlight"><pre><span></span><code>ipython nbconvert --to html --template basic filename.ipynb
</code></pre></div>
<h2 id="2-paste-html-in-blog">2. Paste HTML in blog<a class="headerlink" href="#2-paste-html-in-blog" title="Permanent link">¶</a></h2>
<p>Note: if you're using the Blogger platform, never switch back to the Compose interface after you use the HTML interface, it changes all your tags.</p>
<h2 id="3-add-css-to-blog-html">3. Add CSS to blog HTML<a class="headerlink" href="#3-add-css-to-blog-html" title="Permanent link">¶</a></h2>
<p>This seems to reproduce the native syntax highlighting of IPython.</p>
<div class="highlight"><pre><span></span><code><span class="nt"><style</span><span class="w"> </span><span class="na">type=</span><span class="s">"text/css"</span><span class="nt">></span>
.highlight{background:<span class="w"> </span>#f8f8f8;<span class="w"> </span>overflow:auto;width:auto;border:solid<span class="w"> </span>gray;border-width:.1em<span class="w"> </span>.1em<span class="w"> </span>.1em<span class="w"> </span>.1em;padding:0em<span class="w"> </span>.5em;border-radius:<span class="w"> </span>4px;}
.k{color:<span class="w"> </span>#338822;<span class="w"> </span>font-weight:<span class="w"> </span>bold;}
.kn{color:<span class="w"> </span>#338822;<span class="w"> </span>font-weight:<span class="w"> </span>bold;}
.mi{color:<span class="w"> </span>#000000;}
.o{color:<span class="w"> </span>#000000;}
.ow{color:<span class="w"> </span>#BA22FF;<span class="w"> </span>font-weight:<span class="w"> </span>bold;}
.nb{color:<span class="w"> </span>#338822;}
.n{color:<span class="w"> </span>#000000;}
.s{color:<span class="w"> </span>#cc2222;}
.se{color:<span class="w"> </span>#cc2222;<span class="w"> </span>font-weight:<span class="w"> </span>bold;}
.si{color:<span class="w"> </span>#C06688;<span class="w"> </span>font-weight:<span class="w"> </span>bold;}
.nn{color:<span class="w"> </span>#4D00FF;<span class="w"> </span>font-weight:<span class="w"> </span>bold;}
<span class="nt"></style></span>
</code></pre></div>
<h2 id="_1">是也乎<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p>原来... <code>IPy[:] notebook</code> 天然就内置了这种能力!</p>
<h2 id="changelog">Changelog<a class="headerlink" href="#changelog" title="Permanent link">¶</a></h2>
<ul>
<li>160322 @TANG ZhiXiong 提醒:<ul>
<li>其实放在 GitHub,然后分享一个 Jupyter 链接是最好的</li>
<li><code>是也乎</code> 这的确是 2015-7 之后更好的解决方案了 ;-)</li>
</ul>
</li>
<li>140107 move into Pelican as zoomquiet.io</li>
<li>131106 pub. <a href="https://medium.com/i-m-h-o/9520fee0b59f">EKR to Chinese programmer — I. M. H. O. — Medium</a></li>
</ul>十大早该知道的Python技巧2014-11-26T00:00:00+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2014-11-26:/top10-Py-idioms-wish-learned-earlier.html<p>原文: <a href="http://prooffreaderplus.blogspot.ca/2014/11/top-10-python-idioms-i-wished-id.html">prooffreader plus: Top 10 Python idioms I wish I'd learned earlier</a></p>
<p><code>Top 10 Python idioms I wish I'd learned earlier</code></p>
<p>I've been programming all my life, but never been a programmer. Most of my work was done in Visual Basic because it's what I was most comfortable with …</p><p>原文: <a href="http://prooffreaderplus.blogspot.ca/2014/11/top-10-python-idioms-i-wished-id.html">prooffreader plus: Top 10 Python idioms I wish I'd learned earlier</a></p>
<p><code>Top 10 Python idioms I wish I'd learned earlier</code></p>
<p>I've been programming all my life, but never been a programmer. Most of my work was done in Visual Basic because it's what I was most comfortable with, plus a smattering of other languages (R, C, JavaScript, etc... Pascal, Applescript, Hypertext and BASIC, which I learned in 1979, if you go far back enough). A couple of years ago, I decided to use Python exclusively so that I could improve my coding. I ended up re-inventing many wheels -- which I didn't mind too much, because I enjoy solving puzzles. But sometimes it's good to have a more efficient, Pythonesque approach, and time after time I found myself having "aha!" moments, realizing I'd been doing things the hard, excessively verbose way for no reason. Here is a list of ten Python idioms that would have made my life much easier if I'd thought to search for them early on.</p>
<p>Missing from this list are some idioms such as list comprehensions and lambda functions, which are very Pythonesque and very efficient and very cool, but also very difficult to miss because they're mentioned on StackOverflow every other answer! Also ternary x if y else z constructions, decorators and generators, because I don't use them very often.</p>
<p>There's also an
<a href="http://nbviewer.ipython.org/github/Prooffreader/Misc_ipynb/blob/master/top_10_python_idioms.ipynb">IPython notebook nbviewer version</a> of this document if you prefer.</p>
<h2 id="1-python-3-style-printing-in-python-2">1. Python 3-style printing in Python 2<a class="headerlink" href="#1-python-3-style-printing-in-python-2" title="Permanent link">¶</a></h2>
<p>One of the things that kept me from concentrating on Python was this whole version 2 - version 3 debacle. Finally I went with Python 2 because all the libraries I wanted were not 3-compatible, and I figured if I needed to, I would laboriously adjust my code later. </p>
<p>But really, the biggest differences in everyday programming are printing and division, and now I just import from future. Now that almost all the libraries I use heavily are v3-compliant, I'll make the switch soon.</p>
<div class="highlight"><pre><span></span><code><span class="n">mynumber</span> <span class="o">=</span> <span class="mi">5</span>
<span class="nb">print</span> <span class="s2">"Python 2:"</span>
<span class="nb">print</span> <span class="s2">"The number is </span><span class="si">%d</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">mynumber</span><span class="p">)</span>
<span class="nb">print</span> <span class="n">mynumber</span> <span class="o">/</span> <span class="mi">2</span><span class="p">,</span>
<span class="nb">print</span> <span class="n">mynumber</span> <span class="o">//</span> <span class="mi">2</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">print_function</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">division</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">Python 3:'</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"The number is </span><span class="si">{}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">mynumber</span><span class="p">))</span>
<span class="nb">print</span><span class="p">(</span><span class="n">mynumber</span> <span class="o">/</span> <span class="mi">2</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s1">' '</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">mynumber</span> <span class="o">//</span> <span class="mi">2</span><span class="p">)</span>
</code></pre></div>
<div class="highlight"><pre><span></span><code>Python 2:
The number is 5
2 2
Python 3:
The number is 5
2.5 2
</code></pre></div>
<p>Oh, and here's an easter egg for C programmers:</p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">braces</span>
<span class="n">File</span> <span class="s2">"<ipython-input-3-2aebb3fc8ecf>"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">braces</span>
<span class="ne">SyntaxError</span><span class="p">:</span> <span class="ow">not</span> <span class="n">a</span> <span class="n">chance</span>
</code></pre></div>
<h2 id="2-enumeratelist">2. enumerate(list)<a class="headerlink" href="#2-enumeratelist" title="Permanent link">¶</a></h2>
<p>It might seem obvious that you should be able to iterate over a list and its index at the same time, but I used counter variables or slices for an embarrassingly long time.</p>
<div class="highlight"><pre><span></span><code><span class="n">mylist</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s2">"It's"</span><span class="p">,</span><span class="w"> </span><span class="s1">'only'</span><span class="p">,</span><span class="w"> </span><span class="s1">'a'</span><span class="p">,</span><span class="w"> </span><span class="s1">'model'</span><span class="p">]</span>
<span class="k">for</span><span class="w"> </span><span class="n">index</span><span class="p">,</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">enumerate</span><span class="p">(</span><span class="n">mylist</span><span class="p">):</span>
<span class="w"> </span><span class="nb">print</span><span class="p">(</span><span class="n">index</span><span class="p">,</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
</code></pre></div>
<div class="highlight"><pre><span></span><code><span class="mf">0</span><span class="w"> </span><span class="n">It</span><span class="err">'</span><span class="n">s</span>
<span class="mf">1</span><span class="w"> </span><span class="kr">on</span><span class="n">ly</span>
<span class="mf">2</span><span class="w"> </span><span class="n">a</span>
<span class="mf">3</span><span class="w"> </span><span class="n">model</span>
</code></pre></div>
<h2 id="3-chained-comparison-operators">3. Chained comparison operators<a class="headerlink" href="#3-chained-comparison-operators" title="Permanent link">¶</a></h2>
<p>Because I was so used to statically typed languages (where this idiom would be ambiguous), it never occurred to me to put two operators in the same expression. In many languages, 4 > 3 > 2 would return as False, because (4 > 3) would be evaluated as a boolean, and then True > 2 would be evaluated as False.</p>
<div class="highlight"><pre><span></span><code>mynumber = 3
if 4 > mynumber > 2:
print("Chained comparison operators work! \n" * 3)
</code></pre></div>
<div class="highlight"><pre><span></span><code>Chained comparison operators work!
Chained comparison operators work!
Chained comparison operators work!
</code></pre></div>
<h2 id="4-collectionscounter">4. collections.Counter<a class="headerlink" href="#4-collectionscounter" title="Permanent link">¶</a></h2>
<p>The collections library is, like, the best thing ever. Stackoverflow turned me on to ordered dicts early on, but I kept using a snippet to create dicts to count occurrences of results in my code. One of these days, I'll figure out a use for collections.deque.</p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">Counter</span>
<span class="kn">from</span> <span class="nn">random</span> <span class="kn">import</span> <span class="n">randrange</span>
<span class="kn">import</span> <span class="nn">pprint</span>
<span class="n">mycounter</span> <span class="o">=</span> <span class="n">Counter</span><span class="p">()</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">):</span>
<span class="n">random_number</span> <span class="o">=</span> <span class="n">randrange</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
<span class="n">mycounter</span><span class="p">[</span><span class="n">random_number</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">mycounter</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
</code></pre></div>
<div class="highlight"><pre><span></span><code><span class="mf">0</span><span class="w"> </span><span class="mf">10</span>
<span class="mf">1</span><span class="w"> </span><span class="mf">10</span>
<span class="mf">2</span><span class="w"> </span><span class="mf">13</span>
<span class="mf">3</span><span class="w"> </span><span class="mf">6</span>
<span class="mf">4</span><span class="w"> </span><span class="mf">6</span>
<span class="mf">5</span><span class="w"> </span><span class="mf">11</span>
<span class="mf">6</span><span class="w"> </span><span class="mf">10</span>
<span class="mf">7</span><span class="w"> </span><span class="mf">14</span>
<span class="mf">8</span><span class="w"> </span><span class="mf">12</span>
<span class="mf">9</span><span class="w"> </span><span class="mf">8</span>
</code></pre></div>
<h2 id="5-dict-comprehensions">5. Dict comprehensions<a class="headerlink" href="#5-dict-comprehensions" title="Permanent link">¶</a></h2>
<p>A rite of passage for a Python programmer is understanding list comprehensions, but eventually I realized dict comprehensions are just as useful -- especially for reversing dicts.</p>
<div class="highlight"><pre><span></span><code><span class="n">my_phrase</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s2">"No"</span><span class="p">,</span><span class="w"> </span><span class="s2">"one"</span><span class="p">,</span><span class="w"> </span><span class="s2">"expects"</span><span class="p">,</span><span class="w"> </span><span class="s2">"the"</span><span class="p">,</span><span class="w"> </span><span class="s2">"Spanish"</span><span class="p">,</span><span class="w"> </span><span class="s2">"Inquisition"</span><span class="p">]</span>
<span class="n">my_dict</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="n">key</span><span class="p">:</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">value</span><span class="p">,</span><span class="w"> </span><span class="n">key</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">enumerate</span><span class="p">(</span><span class="n">my_phrase</span><span class="p">)}</span>
<span class="nb">print</span><span class="p">(</span><span class="n">my_dict</span><span class="p">)</span>
<span class="n">reversed_dict</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="n">value</span><span class="p">:</span><span class="w"> </span><span class="n">key</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">my_dict</span><span class="o">.</span><span class="n">items</span><span class="p">()}</span>
<span class="nb">print</span><span class="p">(</span><span class="n">reversed_dict</span><span class="p">)</span>
</code></pre></div>
<div class="highlight"><pre><span></span><code>{'Inquisition': 5, 'No': 0, 'expects': 2, 'one': 1, 'Spanish': 4, 'the': 3}
{0: 'No', 1: 'one', 2: 'expects', 3: 'the', 4: 'Spanish', 5: 'Inquisition'}
</code></pre></div>
<h2 id="6-executing-shell-commands-with-subprocess">6. Executing shell commands with subprocess<a class="headerlink" href="#6-executing-shell-commands-with-subprocess" title="Permanent link">¶</a></h2>
<p>I used to use the os library exclusively to manipulate files; now I can even programmatically call complex command-line tools like ffmpeg for video editing</p>
<p>(And yes, I use Windows, so do all of my clients. But I have the good grace to be embarrassed about it!)</p>
<p>Note that the particular subprocess I picked would be much better done with the os library; I just wanted a command everyone would be familiar with. And in general, shell=True is a VERY bad idea, I put it here so that the command output would appear in the IPython notebook cell. Don't try this at home, kids!</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">subprocess</span>
<span class="n">output</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">check_output</span><span class="p">(</span><span class="s1">'dir'</span><span class="p">,</span> <span class="n">shell</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">output</span><span class="p">)</span>
<span class="n">Volume</span> <span class="ow">in</span> <span class="n">drive</span> <span class="n">C</span> <span class="ow">is</span> <span class="n">OS</span>
<span class="n">Volume</span> <span class="n">Serial</span> <span class="n">Number</span> <span class="ow">is</span> <span class="p">[</span><span class="n">REDACTED</span><span class="p">]</span>
<span class="n">Directory</span> <span class="n">of</span> <span class="n">C</span><span class="p">:</span>\<span class="n">Users</span>\<span class="n">David</span>\<span class="n">Documents</span>\<span class="p">[</span><span class="n">REDACTED</span><span class="p">]</span>
</code></pre></div>
<div class="highlight"><pre><span></span><code><span class="mf">2014</span><span class="o">-</span><span class="mf">11</span><span class="o">-</span><span class="mf">26</span><span class="w"> </span><span class="mf">06</span><span class="p">:</span><span class="mf">04</span><span class="w"> </span><span class="n">AM</span><span class="w"> </span><span class="o"><</span><span class="n">DIR</span><span class="o">></span><span class="w"> </span><span class="mf">.</span>
<span class="mf">2014</span><span class="o">-</span><span class="mf">11</span><span class="o">-</span><span class="mf">26</span><span class="w"> </span><span class="mf">06</span><span class="p">:</span><span class="mf">04</span><span class="w"> </span><span class="n">AM</span><span class="w"> </span><span class="o"><</span><span class="n">DIR</span><span class="o">></span><span class="w"> </span><span class="mf">..</span>
<span class="mf">2014</span><span class="o">-</span><span class="mf">11</span><span class="o">-</span><span class="mf">23</span><span class="w"> </span><span class="mf">11</span><span class="p">:</span><span class="mf">47</span><span class="w"> </span><span class="n">AM</span><span class="w"> </span><span class="o"><</span><span class="n">DIR</span><span class="o">></span><span class="w"> </span><span class="mf">.</span><span class="n">git</span>
<span class="mf">2014</span><span class="o">-</span><span class="mf">11</span><span class="o">-</span><span class="mf">26</span><span class="w"> </span><span class="mf">06</span><span class="p">:</span><span class="mf">06</span><span class="w"> </span><span class="n">AM</span><span class="w"> </span><span class="o"><</span><span class="n">DIR</span><span class="o">></span><span class="w"> </span><span class="mf">.</span><span class="n">ipynb_checkpoints</span>
<span class="mf">2014</span><span class="o">-</span><span class="mf">11</span><span class="o">-</span><span class="mf">23</span><span class="w"> </span><span class="mf">08</span><span class="p">:</span><span class="mf">59</span><span class="w"> </span><span class="n">AM</span><span class="w"> </span><span class="o"><</span><span class="n">DIR</span><span class="o">></span><span class="w"> </span><span class="n">CCCma</span>
<span class="mf">2014</span><span class="o">-</span><span class="mf">09</span><span class="o">-</span><span class="mf">03</span><span class="w"> </span><span class="mf">06</span><span class="p">:</span><span class="mf">58</span><span class="w"> </span><span class="n">AM</span><span class="w"> </span><span class="mf">19</span><span class="p">,</span><span class="mf">450</span><span class="w"> </span><span class="n">colorbrewdict</span><span class="mf">.</span><span class="n">py</span>
<span class="mf">2014</span><span class="o">-</span><span class="mf">09</span><span class="o">-</span><span class="mf">03</span><span class="w"> </span><span class="mf">06</span><span class="p">:</span><span class="mf">58</span><span class="w"> </span><span class="n">AM</span><span class="w"> </span><span class="mf">92</span><span class="p">,</span><span class="mf">175</span><span class="w"> </span><span class="n">imagecompare</span><span class="mf">.</span><span class="n">ipynb</span>
<span class="mf">2014</span><span class="o">-</span><span class="mf">11</span><span class="o">-</span><span class="mf">23</span><span class="w"> </span><span class="mf">08</span><span class="p">:</span><span class="mf">41</span><span class="w"> </span><span class="n">AM</span><span class="w"> </span><span class="o"><</span><span class="n">DIR</span><span class="o">></span><span class="w"> </span><span class="n">Japan_Earthquakes</span>
<span class="mf">2014</span><span class="o">-</span><span class="mf">09</span><span class="o">-</span><span class="mf">03</span><span class="w"> </span><span class="mf">06</span><span class="p">:</span><span class="mf">58</span><span class="w"> </span><span class="n">AM</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="mf">100</span><span class="w"> </span><span class="n">LICENSE</span>
<span class="mf">2014</span><span class="o">-</span><span class="mf">09</span><span class="o">-</span><span class="mf">03</span><span class="w"> </span><span class="mf">06</span><span class="p">:</span><span class="mf">58</span><span class="w"> </span><span class="n">AM</span><span class="w"> </span><span class="mf">5</span><span class="p">,</span><span class="mf">263</span><span class="w"> </span><span class="n">monty_monte</span><span class="mf">.</span><span class="n">ipynb</span>
<span class="mf">2014</span><span class="o">-</span><span class="mf">09</span><span class="o">-</span><span class="mf">03</span><span class="w"> </span><span class="mf">06</span><span class="p">:</span><span class="mf">58</span><span class="w"> </span><span class="n">AM</span><span class="w"> </span><span class="mf">31</span><span class="p">,</span><span class="mf">082</span><span class="w"> </span><span class="n">pocket_tumblr_reddit_api</span><span class="mf">.</span><span class="n">ipynb</span>
<span class="mf">2014</span><span class="o">-</span><span class="mf">11</span><span class="o">-</span><span class="mf">26</span><span class="w"> </span><span class="mf">06</span><span class="p">:</span><span class="mf">04</span><span class="w"> </span><span class="n">AM</span><span class="w"> </span><span class="mf">3</span><span class="p">,</span><span class="mf">211</span><span class="w"> </span><span class="kr">READ</span><span class="n">ME</span><span class="mf">.</span><span class="n">md</span>
<span class="mf">2014</span><span class="o">-</span><span class="mf">11</span><span class="o">-</span><span class="mf">26</span><span class="w"> </span><span class="mf">06</span><span class="p">:</span><span class="mf">14</span><span class="w"> </span><span class="n">AM</span><span class="w"> </span><span class="mf">19</span><span class="p">,</span><span class="mf">898</span><span class="w"> </span><span class="kr">to</span><span class="n">p_10_python_idioms</span><span class="mf">.</span><span class="n">ipynb</span>
<span class="mf">2014</span><span class="o">-</span><span class="mf">09</span><span class="o">-</span><span class="mf">03</span><span class="w"> </span><span class="mf">06</span><span class="p">:</span><span class="mf">58</span><span class="w"> </span><span class="n">AM</span><span class="w"> </span><span class="mf">5</span><span class="p">,</span><span class="mf">813</span><span class="w"> </span><span class="n">tree_convert_mega_to_gexf</span><span class="mf">.</span><span class="n">ipynb</span>
<span class="mf">2014</span><span class="o">-</span><span class="mf">09</span><span class="o">-</span><span class="mf">03</span><span class="w"> </span><span class="mf">06</span><span class="p">:</span><span class="mf">58</span><span class="w"> </span><span class="n">AM</span><span class="w"> </span><span class="mf">5</span><span class="p">,</span><span class="mf">453</span><span class="w"> </span><span class="n">tree_convert_mega_to_json</span><span class="mf">.</span><span class="n">ipynb</span>
<span class="mf">2014</span><span class="o">-</span><span class="mf">09</span><span class="o">-</span><span class="mf">03</span><span class="w"> </span><span class="mf">06</span><span class="p">:</span><span class="mf">58</span><span class="w"> </span><span class="n">AM</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="mf">211</span><span class="w"> </span><span class="n">tree_convert_newick_to_json</span><span class="mf">.</span><span class="n">py</span>
<span class="mf">2014</span><span class="o">-</span><span class="mf">09</span><span class="o">-</span><span class="mf">03</span><span class="w"> </span><span class="mf">06</span><span class="p">:</span><span class="mf">58</span><span class="w"> </span><span class="n">AM</span><span class="w"> </span><span class="mf">55</span><span class="p">,</span><span class="mf">970</span><span class="w"> </span><span class="n">weather_ML</span><span class="mf">.</span><span class="n">ipynb</span>
<span class="w"> </span><span class="mf">11</span><span class="w"> </span><span class="n">File</span><span class="p">(</span><span class="n">s</span><span class="p">)</span><span class="w"> </span><span class="mf">240</span><span class="p">,</span><span class="mf">626</span><span class="w"> </span><span class="n">bytes</span>
<span class="w"> </span><span class="mf">6</span><span class="w"> </span><span class="n">Dir</span><span class="p">(</span><span class="n">s</span><span class="p">)</span><span class="w"> </span><span class="mf">180</span><span class="p">,</span><span class="mf">880</span><span class="p">,</span><span class="mf">490</span><span class="p">,</span><span class="mf">496</span><span class="w"> </span><span class="n">bytes</span><span class="w"> </span><span class="nb">fre</span><span class="n">e</span>
</code></pre></div>
<h2 id="7-dict-get-and-iteritems-methods">7. dict .get() and .iteritems() methods<a class="headerlink" href="#7-dict-get-and-iteritems-methods" title="Permanent link">¶</a></h2>
<p>Having a default value when a key does not exist has all kinds of uses, and just like enumerate() for lists, you can iterate over key, value tuples in dicts</p>
<div class="highlight"><pre><span></span><code>my_dict = {'name': 'Lancelot', 'quest': 'Holy Grail', 'favourite_color': 'blue'}
print(my_dict.get('airspeed velocity of an unladen swallow', 'African or European?\n'))
for key, value in my_dict.iteritems():
print(key, value, sep=": ")
</code></pre></div>
<div class="highlight"><pre><span></span><code>African or European?
quest: Holy Grail
name: Lancelot
favourite_color: blue
</code></pre></div>
<h2 id="8-tuple-unpacking-for-switching-variables">8. Tuple unpacking for switching variables<a class="headerlink" href="#8-tuple-unpacking-for-switching-variables" title="Permanent link">¶</a></h2>
<p>Do you know how many times I had to use a third, temporary dummy variable in VB? c = a; a = b; b = c?</p>
<div class="highlight"><pre><span></span><code>a = 'Spam'
b = 'Eggs'
print(a, b)
a, b = b, a
print(a, b)
</code></pre></div>
<div class="highlight"><pre><span></span><code>Spam Eggs
Eggs Spam
</code></pre></div>
<h2 id="9-introspection-tools">9. Introspection tools<a class="headerlink" href="#9-introspection-tools" title="Permanent link">¶</a></h2>
<p>I was aware of dir(), but I had assumed help() would do the same thing as IPython's ? magic command. It does way more. (This post has been updated after some great advice from reddit's /r/python which, indeed, I wish I'd known about before!)</p>
<div class="highlight"><pre><span></span><code>my_dict = {'That': 'an ex-parrot!'}
help(my_dict)
</code></pre></div>
<p>Help on dict object:</p>
<div class="highlight"><pre><span></span><code><span class="k">class</span><span class="w"> </span><span class="n">dict</span><span class="p">(</span><span class="k">object</span><span class="p">)</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">dict</span><span class="p">()</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">empty</span><span class="w"> </span><span class="k">dictionary</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">dict</span><span class="p">(</span><span class="n">mapping</span><span class="p">)</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="k">dictionary</span><span class="w"> </span><span class="n">initialized</span><span class="w"> </span><span class="k">from</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">mapping</span><span class="w"> </span><span class="k">object</span><span class="s1">'s</span>
<span class="s1"> | (key, value) pairs</span>
<span class="s1"> | dict(iterable) -> new dictionary initialized as if via:</span>
<span class="s1"> | d = {}</span>
<span class="s1"> | for k, v in iterable:</span>
<span class="s1"> | d[k] = v</span>
<span class="s1"> | dict(**kwargs) -> new dictionary initialized with the name=value pairs</span>
<span class="s1"> | in the keyword argument list. For example: dict(one=1, two=2)</span>
<span class="s1"> | </span>
<span class="s1"> | Methods defined here:</span>
<span class="s1"> | </span>
<span class="s1"> | __cmp__(...)</span>
<span class="s1"> | x.__cmp__(y) <==> cmp(x,y)</span>
<span class="s1"> | </span>
<span class="s1"> | __contains__(...)</span>
<span class="s1"> | D.__contains__(k) -> True if D has a key k, else False</span>
<span class="s1"> | </span>
<span class="s1"> | __delitem__(...)</span>
<span class="s1"> | x.__delitem__(y) <==> del x[y]</span>
<span class="s1"> | </span>
<span class="s1"> | __eq__(...)</span>
<span class="s1"> | x.__eq__(y) <==> x==y</span>
<span class="s1"> | </span>
<span class="s1">[TRUNCATED FOR SPACE]</span>
<span class="s1"> | </span>
<span class="s1"> | update(...)</span>
<span class="s1"> | D.update([E, ]**F) -> None. Update D from dict/iterable E and F.</span>
<span class="s1"> | If E present and has a .keys() method, does: for k in E: D[k] = E[k]</span>
<span class="s1"> | If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v</span>
<span class="s1"> | In either case, this is followed by: for k in F: D[k] = F[k]</span>
<span class="s1"> | </span>
<span class="s1"> | values(...)</span>
<span class="s1"> | D.values() -> list of D'</span><span class="n">s</span><span class="w"> </span><span class="k">values</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">viewitems</span><span class="p">(...)</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">D</span><span class="p">.</span><span class="n">viewitems</span><span class="p">()</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="k">set</span><span class="o">-</span><span class="ow">like</span><span class="w"> </span><span class="k">object</span><span class="w"> </span><span class="n">providing</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="k">view</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">D</span><span class="s1">'s items</span>
<span class="s1"> | </span>
<span class="s1"> | viewkeys(...)</span>
<span class="s1"> | D.viewkeys() -> a set-like object providing a view on D'</span><span class="n">s</span><span class="w"> </span><span class="n">keys</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">viewvalues</span><span class="p">(...)</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">D</span><span class="p">.</span><span class="n">viewvalues</span><span class="p">()</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="n">an</span><span class="w"> </span><span class="k">object</span><span class="w"> </span><span class="n">providing</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="k">view</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">D</span><span class="err">'</span><span class="n">s</span><span class="w"> </span><span class="k">values</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="o">----------------------------------------------------------------------</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="k">Data</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">other</span><span class="w"> </span><span class="n">attributes</span><span class="w"> </span><span class="n">defined</span><span class="w"> </span><span class="nl">here</span><span class="p">:</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">__hash__</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">None</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">__new__</span><span class="w"> </span><span class="o">=</span><span class="w"> </span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">T</span><span class="p">.</span><span class="n">__new__</span><span class="p">(</span><span class="n">S</span><span class="p">,</span><span class="w"> </span><span class="p">...)</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="k">object</span><span class="w"> </span><span class="k">with</span><span class="w"> </span><span class="n">type</span><span class="w"> </span><span class="n">S</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">subtype</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">T</span>
</code></pre></div>
<h2 id="10-pep-8-compliant-string-chaining">10. PEP-8 compliant string chaining<a class="headerlink" href="#10-pep-8-compliant-string-chaining" title="Permanent link">¶</a></h2>
<p><a href="https://www.python.org/dev/peps/pep-0008">PEP8</a>
is the style guide for Python code. Among other things, it directs that lines not be over 80 characters long and that indenting by consistent over line breaks.</p>
<p>This can be accomplished with a combination of backslashes \; parentheses () with commas , ; and addition operators +; but every one of these solutions is awkward for multiline strings. There is a multiline string signifier, the triple quote, but it does not allow consistent indenting over line breaks. </p>
<p>There is a solution: parentheses without commas. I don't know why this works, but I'm glad it does.</p>
<div class="highlight"><pre><span></span><code>my_long_text = ("We are no longer the knights who say Ni! "
"We are now the knights who say ekki-ekki-"
"ekki-p'tang-zoom-boing-z'nourrwringmm!")
print(my_long_text)
</code></pre></div>
<p>We are no longer the knights who say Ni! We are now the knights who say ekki-ekki-ekki-p'tang-zoom-boing-z'nourrwringmm!</p>
<h2 id="_1">是也乎<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<h2 id="changelog">Changelog<a class="headerlink" href="#changelog" title="Permanent link">¶</a></h2>
<ul>
<li>141130 move into Pelican as zoomquiet.io</li>
</ul>Mavericks 中用 sshfs2014-10-24T00:00:00+08:002015-05-14T21:47:56+08:00Zoom.Quiettag:blog.zoomquiet.io,2014-10-24:/sshfs-in-mavericks.html
<h1 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h1>
<p>自从 2011-12-16 入手 MBP 以来,就发现只有 sshfs 来连接各种系统的硬盘最方便</p>
<ul>
<li>依赖少, 双方有 ssh 就好</li>
<li>配置少, ssh 服务的启动没有 smb …</li></ul>
<h1 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h1>
<p>自从 2011-12-16 入手 MBP 以来,就发现只有 sshfs 来连接各种系统的硬盘最方便</p>
<ul>
<li>依赖少, 双方有 ssh 就好</li>
<li>配置少, ssh 服务的启动没有 smb 服务那么多的配置</li>
<li>自动断, 不会象 smb 死占一个虚假的挂接点</li>
</ul>
<h1 id="_2">问题<a class="headerlink" href="#_2" title="Permanent link">¶</a></h1>
<p>每次 brew 出点小问题,就导致 sshfs 或是不痛快;</p>
<p>目测已经折腾过至少4次了</p>
<ul>
<li>送修理两次</li>
<li>从 10.6 升级 到 10.9 一次</li>
<li>brew 在硬盘权限修订后,完全崩溃,重新安装 又一次</li>
</ul>
<h1 id="_3">分析<a class="headerlink" href="#_3" title="Permanent link">¶</a></h1>
<p>毕竟 sshfs 依赖 FUSE 这种 plan9 发展来的神物,
是第三方的东西...</p>
<p>而且历史上:</p>
<ul>
<li>fuse4x</li>
<li>macfuse</li>
<li>osxfuse</li>
<li>...</li>
</ul>
<p>出现过很多靠谱不靠谱的...</p>
<h1 id="_4">解决<a class="headerlink" href="#_4" title="Permanent link">¶</a></h1>
<p>认真根据 homebrew 上最新 issue 的指引</p>
<ul>
<li>先停了以往各种版本的 <code>FUSE</code></li>
<li>正常的安装</li>
</ul>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>brew<span class="w"> </span>install<span class="w"> </span>sshfs
</code></pre></div>
<p>由脚本自动安装所有依赖包.</p>
<p>并根据安装提示进行必要的系统配置</p>
<div class="highlight"><pre><span></span><code><span class="n">sudo</span><span class="w"> </span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">cp</span><span class="w"> </span><span class="o">-</span><span class="n">RfX</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">opt</span><span class="o">/</span><span class="n">osxfuse</span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Filesystems</span><span class="o">/</span><span class="n">osxfusefs</span><span class="o">.</span><span class="n">fs</span><span class="w"> </span>\
<span class="w"> </span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Filesystems</span><span class="o">/</span>
<span class="n">sudo</span><span class="w"> </span><span class="n">chmod</span><span class="w"> </span><span class="o">+</span><span class="n">s</span><span class="w"> </span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Filesystems</span><span class="o">/</span><span class="n">osxfusefs</span><span class="o">.</span><span class="n">fs</span><span class="o">/</span><span class="n">Support</span><span class="o">/</span><span class="n">load_osxfusefs</span>
</code></pre></div>
<p>首次,进行挂接时,会有驱动非官方的警告,知道就好,
其它一切正常的了 ;-)</p>
<p>参考:</p>
<ul>
<li><a href="http://www.jesusherman.com/blog/general/montar-sshfs-en-os-x-mavericks/">Montar SSHFS en OS X Mavericks</a></li>
<li><a href="http://michael.terretta.com/fix-to-remove-or-uninstall-macfuse-on-mountain-lion-when-you-get-the-error-macfuse-uninstaller-can-not-find-the-archive-dot-bom-for-macfuse-core-package-dot">Fix to remove or uninstall MacFuse on Mountain Lion when you get the error "MacFUSE Uninstaller: Can not find the Archive.bom for MacFUSE Core package." - Crude Technologies</a></li>
<li><a href="https://discussions.apple.com/message/18355704#18355704">how to remove macfuse and ntfs 3g on osx lion? | Apple Support Communities</a></li>
<li>... etc.</li>
</ul>寻路ing Guido van Rossum2014-09-21T13:13:13+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2014-09-21:/guido-finding-his-way.html
<p><a href="https://medium.com/dropbox-makers/guido-van-rossum-on-finding-his-way-e018e8b5f6b1">Guido van Rossum on finding his way — Dropbox Makers — Medium</a></p>
<p>~ Python 缔造者,当前 Dropbox 工程师, 近期编程思考</p>
<p>Guido van Rossum 作为Python 的创造者,
以及 <code>仁慈的独裁者</code> (又名 BDFL).
在此篇 …</p>
<p><a href="https://medium.com/dropbox-makers/guido-van-rossum-on-finding-his-way-e018e8b5f6b1">Guido van Rossum on finding his way — Dropbox Makers — Medium</a></p>
<p>~ Python 缔造者,当前 Dropbox 工程师, 近期编程思考</p>
<p>Guido van Rossum 作为Python 的创造者,
以及 <code>仁慈的独裁者</code> (又名 BDFL).
在此篇采访中,反思了近来的思考,
以及在 Dropbox 的经历.
本文也召示了接下来老爹准备折腾什么.</p>
<p>(<code>译注:</code> 大妈无责任式快译, 只是作为私人阅读笔记性质的存在,
强烈建议大家去原文自行理解一番,并能拨冗回来指点大妈的理解之谬 ;-)</p>
<h2 id="_1">程序猿前,你是如何成为电子爱好者的?<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p>嚓了,这事儿忒久了,久到基本记忆不能了,
只是记得以前对电子很迷就是了.</p>
<h2 id="_2">那会儿子是怎么聚集小伙伴们的?<a class="headerlink" href="#_2" title="Permanent link">¶</a></h2>
<p>高中时在课堂上相遇的,
一起折腾物理老师指导下的各种电子设备.</p>
<p>整个高中只是对未来职业有个模糊的概念,
认定自个儿在语言/社科上是没什么天份的,
所以,决定进入数学专业.</p>
<h2 id="_3">最后乍从电子转变为程序猿的?<a class="headerlink" href="#_3" title="Permanent link">¶</a></h2>
<p>在Amsterdam大学,折腾数学时,
涉及有编程,接触到大型计算机后,
立即发现了俺真正的激情所在.</p>
<p><img alt="AOw_zZbFbtEJAzwRQ" src="https://d262ilb51hltx0.cloudfront.net/max/700/1*5Z4e-AOw_zZbFbtEJAzwRQ.jpeg"/></p>
<p>~ 旧金山 Dropbox 内的 Hack week 上,Guido 谈及了Py 3 / Dan Stroud 拍摄</p>
<h2 id="_4">对计算机科学的兴趣所在?<a class="headerlink" href="#_4" title="Permanent link">¶</a></h2>
<p>通过业余电子爱好,接触到了一系列计算设备,
得以真正理解计算机,
并确信,编程比电子好玩的多.
而数学,无论多高端的课目,好象都和自己没什么关系.</p>
<p>但是,专业上那时,没有办法灵活的转变方向,
于是俺申请了大学数据中心兼职位置,
开始长达5年的自学,
即,本质上几近辍学.</p>
<h2 id="mog">MOG,乍回事儿?!<a class="headerlink" href="#mog" title="Permanent link">¶</a></h2>
<p>这份工作很赞,
而且,遇到了好人,
数据中心的一位教授鼓励俺说: "小子,不错嘦你毕业,这儿可以是你的全职岗位!"
(笑ing)</p>
<p>结果就这么在岗位上毕业,并进入了研究所,
真的全职程序猿了.</p>
<h2 id="_5">推上曰过:"在米国我是荷兰人,但在荷兰我又表现的很美国#纠结",那么哪儿是你感觉最象自家的?<a class="headerlink" href="#_5" title="Permanent link">¶</a></h2>
<p>当然,在自个儿屋子里时..
(笑ing)</p>
<p>俺老婆是老美,两儿子也都说E文,
在米国也呆了超过18年,
已经很难想象会回欧洲了!</p>
<p>目测余生多数时间肯定在米国了,
而且就在湾区,这绝对是一个伟大的地方.</p>
<h2 id="dropbox">在Dropbox最近折腾了什么?<a class="headerlink" href="#dropbox" title="Permanent link">¶</a></h2>
<p>俺已经完成
<a href="https://www.dropbox.com/developers/datastore">Datastore API</a>
有日子了,
今天上线,将发布给用户为
<a href="https://www.dropbox.com/developers/blog/107/new-datastore-features-shared-datastores-local-datastores-and-datastore-webhooks">share datastores</a> </p>
<p><img alt="NMJBScQgtLZE0zmeOA1nJw" src="https://d262ilb51hltx0.cloudfront.net/max/800/1*NMJBScQgtLZE0zmeOA1nJw.png"/></p>
<h2 id="_6">带团队,还是更加独立?<a class="headerlink" href="#_6" title="Permanent link">¶</a></h2>
<p>对于这一特殊的数据功能,
俺独立完成主要工作,
另外两位,主要进行测试,
在发布后,将会融入更大的团队,
并接纳实习生
...</p>
<h2 id="dropbox_1">进入 Dropbox 时,你要求当程序猿而不是经理,这对你很重要嘛?<a class="headerlink" href="#dropbox_1" title="Permanent link">¶</a></h2>
<p>因为俺更加喜欢实际的编程,
以往俺被关进了一个团队,
无论编程还是作管理,
从来没有令俺舒服过.
当然,随着时间的推移,俺的领导能力有所增长,
可是,终究,俺是喜欢编程多过告诉其它人应该怎么作.</p>
<h2 id="dropbox-python-bdfl">你乍平衡 Dropbox 工程师和 Python BDFL 两种角色的?<a class="headerlink" href="#dropbox-python-bdfl" title="Permanent link">¶</a></h2>
<p>在时间管理方面,
这两个角色的确是冲突的.
我并没有进行强制性的预订,为这两种角色.</p>
<p>实践中,哪个角色必须投入更多精力时,
就相应的减少另一个角色的.</p>
<p><img alt="AriSTNW_leEP85c7r" src="https://d262ilb51hltx0.cloudfront.net/max/1200/1*AriSTNW_leEP85c7r-wcew.jpeg"/></p>
<p>~ 在DBX 2013 上 Guido 介绍 Dropbox 的数据存储. / Doug Cody 拍摄</p>
<h2 id="dropbox_2">在 Dropbox 的工作什么令你最得劲?<a class="headerlink" href="#dropbox_2" title="Permanent link">¶</a></h2>
<p>在这儿,最令人满意的无外乎,
能见到这么堆热情/专注/有生产力/强大的人,
如此热衷的在推动产品和功能.</p>
<p>身处其中,本身就非常赞!</p>
<p>(<code>译注:</code>
细思恐极哪,这意味着 Google 的团队的确如 <code>王珢</code> 所言,
不是那么的...
)</p>
<h2 id="hack-week">你在 Hack Week 的项目是什么?<a class="headerlink" href="#hack-week" title="Permanent link">¶</a></h2>
<p>Python 的静态类型.
来源自我们的一位实习工程师, Jukka Lehtosalo 的博士论文,
他实际上完成了一个原型,
在一周时间里,
我们一组7 人,对原型进行了改进,并完成了大量的工具.</p>
<p>至今并没有形成完备的产品,
但是,大家都很期待这一够力的创意能产生出什么来.</p>
<h2 id="_7">为毛你选择静态类型这一项目?<a class="headerlink" href="#_7" title="Permanent link">¶</a></h2>
<p>俺认为增加静态类型,
对未来是有益的,
至少能先帮助 Dropbox 转换自身的 Python 2 和 3 的代码</p>
<p><img alt="yemdZovwCmvm7b2Dkm6SRQ" src="https://d262ilb51hltx0.cloudfront.net/max/800/1*yemdZovwCmvm7b2Dkm6SRQ.png"/></p>
<p>Dropbox 的第一行代码就是Python.
而 Python Bees 将成为 DBX 以及 更早 Dropbox hack weeks 的新特性.</p>
<h2 id="python">如何平衡程序猿最新需求和 Python 长线版本间的冲突?<a class="headerlink" href="#python" title="Permanent link">¶</a></h2>
<p>Python 有一个很大的团队,
长期审核进入 Python 的特性.
在经过20多年的运营,我们已经很熟悉这一编程语言应该坚守的东西.</p>
<p>语言变化太快,用户将抱怨项目总是无法稳定;
变化太慢,程序猿就抱怨错误总是不修订或是要求的功能从来不响应;
这里有种非常微妙的平衡在其中!</p>
<p>所以,一般情况下,将变化快的东西,放在库中支持,
优先确保核心语言特性的稳定,
这样大家都根据需要安装对应的开源库就好.</p>
<p>学习到这点,对俺来说非常不可思异.
目前俺处于非常舒适的状态,
即使现在俺退出,后续开发者也能理解怎么取舍的.</p>
<h2 id="python_1">有想过从 Python 社区退休? 有规划这事儿卟?<a class="headerlink" href="#python_1" title="Permanent link">¶</a></h2>
<p>(笑ing)
这是一个很好的组合问题.
因为,俺的确有这么想过,
不过,当前还仅仅是想着.</p>
<h2 id="python_2">有没担心过更多新语言出现并替代 Python ?<a class="headerlink" href="#python_2" title="Permanent link">¶</a></h2>
<p>因为发现的一种现象,令俺从未不担心这事儿.</p>
<p>那就是总是有人在切换开发语言,
他们花了 三周/6周/两年, 就成为某种语言专家.
基于这种经验,他们就担心,
对 Python 的学习,可能也很快过时,必须重新开始.</p>
<p>我见过各种语言/系统的普及以及更替,
但是,我不知道 Python 的这种兴衰周期,
5年?15年?
我当然希望 Python 持续吸收新的语言特性,发展下去,适应新的时代.
同时也期待,有更好的语言,借用 Python 的思想,
在不同的形式上结合其它语言,发展出不同的道路来.</p>
<p><img alt="omEEAJapdc0XY9IfR" src="https://d262ilb51hltx0.cloudfront.net/max/1200/1*omEEAJapdc0XY9IfR-mFlA.jpeg"/></p>
<p>~ 在 DBX 2013 Python Bee 集会上,Guido 和 Dropbox CEO Drew Houston
联手庆贺. / Doug Cody 拍摄</p>
<p><img alt="4saVabl5aGfdTVuPLBNBCQ" src="https://d262ilb51hltx0.cloudfront.net/max/1200/1*4saVabl5aGfdTVuPLBNBCQ.jpeg"/></p>
<p><img alt="ziwbjd1WMkmuuoFK9q0Q" src="https://d262ilb51hltx0.cloudfront.net/max/1200/1*w-ziwbjd1WMkmuuoFK9q0Q.jpeg"/></p>
<h2 id="_8">在 <a href="http://neopythonic.blogspot.com/2013/10/letter-to-young-programmer.html">给年轻程序猿的信</a> 中,你号召要有大梦想,可现实挑战是大梦想忒多了,面对这么多的机会,你有什么建议给早鸟们?<a class="headerlink" href="#_8" title="Permanent link">¶</a></h2>
<p>(<code>译注:</code>中译: <a href="http://blog.zoomquiet.io/guido-letter-2-young.html">Letter to a young programmer</a>
)</p>
<p>早期职业生涯?
俺可能没有什么很好的经验,
因为,俺可是用了很长时间,才明白自个儿应该作什么的.
回想,基本上只是开开心心的编程,一切就自然来到面前.</p>
<p>实际上,俺从来没有争取过什么工作,
只是等待,直到有人询问合作意愿,才进行考虑.</p>
<p>我从不强调一切在掌握之中,
的确有那么一种病叫:<code>怕错过</code></p>
<p>实际上, 那些尝试控制一切的人并没有比我多快乐些什么.</p>
<p>所以,对于长期职业,你并不能真正控制一切.
有时,对一件事儿决定太快,
你可能就真正错过了一次意想不到机会.</p>
<p>...</p>
<h2 id="changlog">Changlog<a class="headerlink" href="#changlog" title="Permanent link">¶</a></h2>
<ul>
<li>140921 蠎周刊:133 期,推荐文章,不自觉的认真读完,形成了这一快译.</li>
</ul>Python 101: 传播Python时几点建议2014-08-08T00:00:00+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2014-08-08:/py101-taching-suggestions.html<p><img alt="/chinese-python-poster" src="https://datalabcc.files.wordpress.com/2014/05/chinese-python-poster.jpg?w=590"/></p>
<p>来自: <a href="http://www.curiousefficiency.org/posts/2014/08/python-teaching-suggestions.html">Some Suggestions for Teaching Python | Curious Efficiency</a>
Nick Coghlan
2014-08-08 12:55</p>
<p>I recently had the chance to attend a Software Carpentry bootcamp at the University of Queensland (as a teaching assistant), as well as seeing a presentation from one of UQ's tutors at PyCon Australia 2014.</p>
<p>While …</p><p><img alt="/chinese-python-poster" src="https://datalabcc.files.wordpress.com/2014/05/chinese-python-poster.jpg?w=590"/></p>
<p>来自: <a href="http://www.curiousefficiency.org/posts/2014/08/python-teaching-suggestions.html">Some Suggestions for Teaching Python | Curious Efficiency</a>
Nick Coghlan
2014-08-08 12:55</p>
<p>I recently had the chance to attend a Software Carpentry bootcamp at the University of Queensland (as a teaching assistant), as well as seeing a presentation from one of UQ's tutors at PyCon Australia 2014.</p>
<p>While many of the issues they encountered were inherent in the complexity of teaching programming, a few seemed like things that could be avoided.</p>
<h2 id="getting-floating-point-results-from-integer-division">Getting floating point results from integer division<a class="headerlink" href="#getting-floating-point-results-from-integer-division" title="Permanent link">¶</a></h2>
<p>In Python 2, integer division copies C in truncating the answer by default:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>python<span class="w"> </span>-c<span class="w"> </span><span class="s2">"print(3/4)"</span>
<span class="m">0</span>
</code></pre></div>
<p>Promoting to floating point requires type coercion, a command line flag or a future import:</p>
<div class="highlight"><pre><span></span><code><span class="err">$</span> <span class="n">python</span> <span class="o">-</span><span class="n">c</span> <span class="s2">"print(float(3)/4)"</span>
<span class="mf">0.75</span>
<span class="err">$</span> <span class="n">python</span> <span class="o">-</span><span class="n">Qnew</span> <span class="o">-</span><span class="n">c</span> <span class="s2">"print(3/4)"</span>
<span class="mf">0.75</span>
<span class="err">$</span> <span class="n">python</span> <span class="o">-</span><span class="n">c</span> <span class="s2">"from __future__ import division; print(3/4)"</span>
<span class="mf">0.75</span>
</code></pre></div>
<p>Python 3 just does the right thing by default, so one way to avoid the problem entirely is to teach Python 3 instead of Python 2:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>python3<span class="w"> </span>-c<span class="w"> </span><span class="s2">"print(3/4)"</span>
<span class="m">0</span>.75
</code></pre></div>
<p>(In both Python 2 and 3, the <code>//</code> floor division operator explicitly requests truncating division when it is desired)</p>
<h2 id="common-python-23-syntax-for-printing-values">Common Python 2/3 syntax for printing values<a class="headerlink" href="#common-python-23-syntax-for-printing-values" title="Permanent link">¶</a></h2>
<p>I've been using Python 2 and 3 in parallel for more than 8 years now (while Python 3.0 was released in 2008, the project started in earnest a couple of years earlier than that, while Python 2.5 was still in development).</p>
<p>One essential trick I have learned in order to make regularly switching back and forth feasible is to limit myself to the common print syntax that works the same in both versions: passing a single argument surrounded by parentheses.</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>python<span class="w"> </span>-c<span class="w"> </span><span class="s1">'print("Hello world!")'</span>
Hello<span class="w"> </span>world!
$<span class="w"> </span>python3<span class="w"> </span>-c<span class="w"> </span><span class="s1">'print("Hello world!")'</span>
Hello<span class="w"> </span>world!
</code></pre></div>
<p>If I need to pass multiple arguments, I'll use string formatting, rather than the implicit concatenation feature.</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>python<span class="w"> </span>-c<span class="w"> </span><span class="s1">'print("{} {}{}".format("Hello", "world", "!"))'</span>
Hello<span class="w"> </span>world!
$<span class="w"> </span>python3<span class="w"> </span>-c<span class="w"> </span><span class="s1">'print("{} {}{}".format("Hello", "world", "!"))'</span>
Hello<span class="w"> </span>world!
</code></pre></div>
<p>Rather than doing this, the Software Carpentry material that was used at the bootcamp I attended used the legacy Python 2 only <code>print</code> syntax extensively, causing examples that otherwise would have worked fine in either version to fail for students that happened to be running Python 3. Adopting the shared syntax for printing values could be enough to make the course largely version independent.</p>
<h2 id="distinguishing-between-returning-and-printing-values">Distinguishing between returning and printing values<a class="headerlink" href="#distinguishing-between-returning-and-printing-values" title="Permanent link">¶</a></h2>
<p>One problem noted both at the bootcamp and by presenters at PyCon Australia was the challenge of teaching students the difference between printing and returning values. The problem is the "Print" part of the Read-Eval-Print-Loop provided by Python's interactive interpreter:</p>
<div class="highlight"><pre><span></span><code>>>> def print_arg(x):
<span class="k">...</span> print(x)
...
>>> def return_arg(x):
<span class="k">...</span> return x
...
>>> print_arg(10)
10
>>> return_arg(10)
10
</code></pre></div>
<p>There's no obvious difference in output at the interactive prompt, especially for types like numbers where the results of <code>str</code> and <code>repr</code> are the same. Even when they're different, those differences may not be obvious to a student:</p>
<div class="highlight"><pre><span></span><code>>>> print_arg("Hello world")
Hello world
>>> return_arg("Hello world")
'Hello world'
</code></pre></div>
<p>While I don't have a definitive answer for this one, an experiment that seems worth trying to me is to teach students how to replace <code>sys.displayhook</code>.
In particular, I suggest demonstrating the following change, and seeing if it helps explain the difference between printing output for display to the user and returning values for further processing:</p>
<div class="highlight"><pre><span></span><code><span class="o">>>></span> <span class="k">def</span> <span class="nf">new_displayhook</span><span class="p">(</span><span class="n">obj</span><span class="p">):</span>
<span class="o">...</span> <span class="k">if</span> <span class="n">obj</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="o">...</span> <span class="nb">print</span><span class="p">(</span><span class="s2">"-> </span><span class="si">{!r}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">obj</span><span class="p">))</span>
<span class="o">...</span>
<span class="o">>>></span> <span class="kn">import</span> <span class="nn">sys</span>
<span class="o">>>></span> <span class="n">sys</span><span class="o">.</span><span class="n">displayhook</span> <span class="o">=</span> <span class="n">new_displayhook</span>
<span class="o">>>></span> <span class="n">print_arg</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
<span class="mi">10</span>
<span class="o">>>></span> <span class="n">return_arg</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
<span class="o">-></span> <span class="mi">10</span>
</code></pre></div>
<p>Understanding the difference between printing and returning is essential to learning to use functions effectively, and tweaking the display of results this way may help make the difference more obvious.</p>
<h2 id="addendum-ipython-including-ipython-notebook">Addendum: IPython (including IPython Notebook)<a class="headerlink" href="#addendum-ipython-including-ipython-notebook" title="Permanent link">¶</a></h2>
<p>The initial examples above focused on the standard CPython runtime, include the default interactive interpreter. The IPython interactive interpreter, including the IPython Notebook, has a couple of interesting differences in behaviour that are relevant to the above comments.</p>
<p>Firstly, it does display return values and printed values differently, prefacing results with an output reference number:</p>
<div class="highlight"><pre><span></span><code>In [1]: print 10
10
In [2]: 10
Out[2]: 10
</code></pre></div>
<p>Secondly, it has an optional "autocall" feature that allows a user to tell IPython to automatically add the missing parentheses to a function call if the user leaves them out:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>ipython3<span class="w"> </span>--autocall<span class="o">=</span><span class="m">1</span><span class="w"> </span>-c<span class="w"> </span><span class="s2">"print 10"</span>
-><span class="w"> </span>print<span class="o">(</span><span class="m">10</span><span class="o">)</span>
<span class="m">10</span>
</code></pre></div>
<p>This is a general purpose feature that allows users to make their IPython sessions behave more like languages that don't have first class functions (most notably, IPython's autocall feature closely resembles MATLAB's "command syntax" notation for calling functions).</p>
<p>It also has the side effect that users that use IPython, have autocall enabled, and don't use any of the more esoteric quirks of the Python 2 <code>print</code> statement (like stream redirection or suppressing the trailing newline) may not even notice that <code>print</code> became an ordinary builtin in Python 3.</p>
<h2 id="changelog">Changelog<a class="headerlink" href="#changelog" title="Permanent link">¶</a></h2>
<ul>
<li>140811 翻译 Weekly issue:127 时发现,转译学习</li>
</ul>为毛俺不担心所谓Python用户流失2014-07-11T00:00:00+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2014-07-11:/why-i-dont-worry-about-pythons-popularity.html<h2 id="why-i-dont-worry-about-python-losing-users">Why I don't worry about Python losing users<a class="headerlink" href="#why-i-dont-worry-about-python-losing-users" title="Permanent link">¶</a></h2>
<p>I just had a need to read two files that were line-delimited lists of domains, consolidate the data, and then output the domains sorted and all lowercased to a new file. It took me 10 lines of Python code and worked perfectly …</p><h2 id="why-i-dont-worry-about-python-losing-users">Why I don't worry about Python losing users<a class="headerlink" href="#why-i-dont-worry-about-python-losing-users" title="Permanent link">¶</a></h2>
<p>I just had a need to read two files that were line-delimited lists of domains, consolidate the data, and then output the domains sorted and all lowercased to a new file. It took me 10 lines of Python code and worked perfectly on the first try.</p>
<p>Out of curiosity and to make sure I keep learning Go (my team at work uses it whenever possible), I decided to re-implement the same functionality. That took
<a href="https://gist.github.com/brettcannon/a2a37cc5aadbc91c02ad">56 lines in Go</a>
. When I went back and refactored the Python code to match the abstractions I used in the Go code it grew to
<a href="https://gist.github.com/brettcannon/82c4fe68bac30f4ed653">17 lines</a>
.</p>
<p>And this sort of thing is exactly why I do not worry about Python's popularity (at least in terms of users). While languages like Go compete with Python on a performance:productivity comparison, when you compare Python to almost any other language based purely on productivity it trounces the competition. And this shouldn't shock anyone when you think about the history of Python. The language was initially created to script
<a href="http://en.wikipedia.org/wiki/Amoeba_(operating_system)">a distributed operating system</a>
. This is why in the '90s and early 2000s the comparison was always Python vs. Perl and then Python vs. Ruby. Only in the 2000s and later did Python get compared to Java or very recently to Go or JavaScript.</p>
<p>And this productivity view of Python also ties into education. With
<a href="http://cacm.acm.org/blogs/blog-cacm/176450-python-is-now-the-most-popular-introductory-teaching-language-at-top-us-universities/fulltext">Python now the most popular intro teaching language at the top U.S. universities</a>
, many people are learning how to program using Python. But exposure early on to a language does not guarantee future usage by someone; I for one did not use Scheme after my intro course. But because Python is such a productive language, the language becomes a staple in one's toolkit of programming. If people learn Python first, then when they need to write a quick script like I did today they will most likely reach for Python than Java or Go or some other language they may be using for their work.</p>
<p>All of this is why I don't worry about Python's demise due to lack of users. People might switch to Go at work because the performance:productivity ratio is very good for their project or team. Or maybe people got frustrated with the Python 2/3 transition and didn't want to base their project at work on Python anymore. It really doesn't matter in terms of the number of users of Python because I'm willing to bet those people still reach for Python when they need a one-off script to solve a problem. And I bet these people still recommend Python when they are asked what people's first programming language should be. In other words I don't worry about our great-for-teaching, highly productive scripting language ever lacking users; Python will always be useful.</p>
<h2 id="changelog">Changelog<a class="headerlink" href="#changelog" title="Permanent link">¶</a></h2>
<ul>
<li>161203 是也乎,( ̄▽ ̄)<ul>
<li>发现没有必要全文翻译,观点很清晰</li>
<li>就生产力方面,当前世界无出其右</li>
<li>嘦是人类创建的软件工程,必然有一个很长时期的混乱期</li>
<li>这个期间,临时的/一次性的 检验/验证/实验性 脚本是必须的</li>
<li>那么通用的 Python 语言简直是无法放弃的</li>
</ul>
</li>
<li>140728 从周刊中发现,决定翻译</li>
</ul>ScrapBook彻查成果2014-07-11T00:00:00+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2014-07-11:/zq-chk4scrapbook.html
<h2 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p>参考:<a href="http://wiki.woodpecker.org.cn/moin/ZqStudy/MyLearningSkill">我的学习&工具</a></p>
<p>从06年,就将个人网络资料收集/整理/发布,
切换为主力使用 <a href="http://www.xuldev.org/scrapbook/">ScrapBook</a> .</p>
<p>这一下子就8年过去了,常用系统也从 Ubuntu 切换为 …</p>
<h2 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p>参考:<a href="http://wiki.woodpecker.org.cn/moin/ZqStudy/MyLearningSkill">我的学习&工具</a></p>
<p>从06年,就将个人网络资料收集/整理/发布,
切换为主力使用 <a href="http://www.xuldev.org/scrapbook/">ScrapBook</a> .</p>
<p>这一下子就8年过去了,常用系统也从 Ubuntu 切换为 MAC,
收集的本地网页也超过了8万个,早已被迫进行了分库.</p>
<p>自动发布的</p>
<ul>
<li>http://floss.zoomquiet.io</li>
<li>http://skm.zoomquiet.io</li>
</ul>
<p>也成为一些朋友常常挖掘的资料库.</p>
<p>可以说, ScrapBook 在 everynote 流行之前,就成功的解决了俺主要的在线网页资料为主的,
外部知识仓库的收集/整理/组合/复用/发布 等等基本功能/服务.</p>
<p>而且, 也通过Python ,完成了辅助的小脚本工具,配合 个人主机/7牛CDN,
完成了自动化的差异发布.</p>
<h3 id="_2">可是!<a class="headerlink" href="#_2" title="Permanent link">¶</a></h3>
<p>参考: <a href="http://blog.zoomquiet.io/livin-scrapbook.html">ScrapBook 生存指南</a></p>
<ul>
<li>从去年开始, 本地 <code>FLOSS</code> 仓库,就已经无法正常进行标准搜索了,一搜索,整个 FireFox 就僵死.</li>
<li>而且,从其它仓库切换进入 FLOSS 时,要等待半分钟以上...</li>
</ul>
<h2 id="_3">期待<a class="headerlink" href="#_3" title="Permanent link">¶</a></h2>
<p>实在太常用,所以,无法忍,而且也不打算切换到 everynote 什么的其它平台上,
作为一头合格的程序猿,就是要自个儿折腾通透哪!</p>
<p>所以,先决定目标:</p>
<ol>
<li>通过进一步拿合理分仓库,有效减少每个仓库包含的网页数量</li>
<li>通过脚本分析 <code>scrapbook.rdf</code> 数据库来清除多余节点(隐藏的无效的)</li>
<li>通过脚本分析 对应 <code>data/</code> 目录中的网页子目录,清除多余的</li>
<li>针对全新的分仓库,建立对应的 7牛 空间,以及对应的 <code>*.zoomquiet.io</code> 子站发布</li>
</ol>
<p>总之就是要加速,无论本地/远程</p>
<h3 id="_4">数据结构<a class="headerlink" href="#_4" title="Permanent link">¶</a></h3>
<p>为了大家平滑的理解折腾之处,先简要说明一下 ScrapBook 的数据结构:</p>
<div class="highlight"><pre><span></span><code>XX仓库/ 对应 Multi-ScrapBook 开启后,不同的Book
+- data 实际本地网页存放入口, 类似 20050205102119 的子目录
+- tree 导出目录树后的 html 入口
+- ...
`- scrapbook.rdf 插件界面使用的 xml 数据仓库
</code></pre></div>
<p><code>scrapbook.rdf 的关键数据约定</code></p>
<div class="highlight"><pre><span></span><code><span class="cp"><?xml version="1.0"?></span>
<span class="nt"><RDF:RDF</span><span class="w"> </span><span class="na">xmlns:NS2=</span><span class="s">"http://amb.vis.ne.jp/mozilla/scrapbook-rdf#"</span>
<span class="w"> </span><span class="na">xmlns:NC=</span><span class="s">"http://home.netscape.com/NC-rdf#"</span>
<span class="w"> </span><span class="na">xmlns:RDF=</span><span class="s">"http://www.w3.org/1999/02/22-rdf-syntax-ns#"</span><span class="nt">></span>
<span class="w"> </span>...
<span class="w"> </span>主体内容
<span class="nt"></RDF:RDF></span>
根列表:
<span class="nt"><RDF:Seq</span><span class="w"> </span><span class="na">RDF:about=</span><span class="s">"urn:scrapbook:root"</span><span class="nt">></span>
<span class="w"> </span>%(rdf_li)s
<span class="w"> </span><span class="nt"></RDF:Seq></span>
目录容器:
<span class="nt"><RDF:Seq</span><span class="w"> </span><span class="na">RDF:about=</span><span class="s">"urn:scrapbook:%(rdf_item)s"</span><span class="nt">></span>
<span class="w"> </span>%(rdf_li)s
<span class="w"> </span><span class="nt"></RDF:Seq></span>
目录节点条目:
<span class="nt"><RDF:li</span><span class="w"> </span><span class="na">RDF:resource=</span><span class="s">"urn:scrapbook:%(rdf_item)s"</span><span class="nt">/></span>
目录节点:
<span class="nt"><RDF:Description</span><span class="w"> </span><span class="na">RDF:about=</span><span class="s">"urn:scrapbook:%(rdf_item)s"</span>
<span class="w"> </span><span class="na">NS2:type=</span><span class="s">"folder"</span>
<span class="w"> </span><span class="na">NS2:id=</span><span class="s">"%(rdf_id)s"</span>
<span class="w"> </span><span class="na">NS2:title=</span><span class="s">"%(rdf_title)s"</span>
<span class="w"> </span><span class="na">NS2:chars=</span><span class="s">""</span>
<span class="w"> </span><span class="na">NS2:icon=</span><span class="s">""</span>
<span class="w"> </span><span class="na">NS2:source=</span><span class="s">""</span>
<span class="w"> </span><span class="na">NS2:comment=</span><span class="s">""</span><span class="w"> </span><span class="nt">/></span>
页面节点:
<span class="nt"><RDF:Description</span><span class="w"> </span><span class="na">RDF:about=</span><span class="s">"urn:scrapbook:%(rdf_item)s"</span>
<span class="w"> </span><span class="na">NS2:type=</span><span class="s">"%(rdf_type)s"</span>
<span class="w"> </span><span class="na">NS2:id=</span><span class="s">"%(rdf_id)s"</span>
<span class="w"> </span><span class="na">NS2:title=</span><span class="s">"%(rdf_title)s"</span>
<span class="w"> </span><span class="na">NS2:comment=</span><span class="s">"%(rdf_comment)s"</span>
<span class="w"> </span><span class="na">NS2:icon=</span><span class="s">"%(rdf_icon)s"</span>
<span class="w"> </span><span class="na">NS2:source=</span><span class="s">"%(rdf_source)s"</span><span class="w"> </span>
<span class="w"> </span><span class="na">NS2:chars=</span><span class="s">"UTF-8"</span><span class="w"> </span><span class="nt">/></span>
笔记节点:
<span class="nt"><RDF:Description</span><span class="w"> </span><span class="na">RDF:about=</span><span class="s">"urn:scrapbook:%(rdf_item)s"</span>
<span class="w"> </span><span class="na">NS2:type=</span><span class="s">"note"</span>
<span class="w"> </span><span class="na">NS2:id=</span><span class="s">"%(rdf_id)s"</span>
<span class="w"> </span><span class="na">NS2:title=</span><span class="s">"%(rdf_title)s"</span>
<span class="w"> </span><span class="na">NS2:chars=</span><span class="s">"UTF-8"</span>
<span class="w"> </span><span class="na">NS2:comment=</span><span class="s">""</span>
<span class="w"> </span><span class="na">NS2:icon=</span><span class="s">""</span>
<span class="w"> </span><span class="na">NS2:source=</span><span class="s">""</span><span class="nt">/></span>
分割线节点:
<span class="nt"><NC:BookmarkSeparator</span><span class="w"> </span><span class="na">RDF:about=</span><span class="s">"urn:scrapbook:%(rdf_item)s"</span>
<span class="w"> </span><span class="na">NS2:type=</span><span class="s">"separator"</span>
<span class="w"> </span><span class="na">NS2:id=</span><span class="s">"%(rdf_id)s"</span>
<span class="w"> </span><span class="na">NS2:title=</span><span class="s">""</span>
<span class="w"> </span><span class="na">NS2:chars=</span><span class="s">""</span>
<span class="w"> </span><span class="na">NS2:comment=</span><span class="s">""</span>
<span class="w"> </span><span class="na">NS2:icon=</span><span class="s">""</span>
<span class="w"> </span><span class="na">NS2:source=</span><span class="s">""</span><span class="w"> </span><span class="nt">/></span>
</code></pre></div>
<p>以上 <code>%(rdf_id)s</code> 之类是 Py 内置模板的语法,
在 <code>scrapbook.rdf</code> 实例中,都是形如: <code>20050205102119</code></p>
<h2 id="_5">折腾<a class="headerlink" href="#_5" title="Permanent link">¶</a></h2>
<p>纪要一下折腾的过程中,要命的关键过程/代码</p>
<h3 id="_6">清查<a class="headerlink" href="#_6" title="Permanent link">¶</a></h3>
<p>一切开始之前,的体积:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>du<span class="w"> </span>-h<span class="w"> </span>*<span class="w"> </span>
...
<span class="m">5</span>.6G<span class="w"> </span>ZqDevRel
<span class="m">6</span>.5G<span class="w"> </span>ZqFLOSS
<span class="m">3</span>.7G<span class="w"> </span>ZqSKM
...
$<span class="w"> </span>ls<span class="w"> </span>ZqDevRel/data/<span class="w"> </span><span class="p">|</span><span class="w"> </span>wc
<span class="w"> </span><span class="m">26214</span><span class="w"> </span><span class="m">26214</span><span class="w"> </span><span class="m">393210</span>
<span class="c1"># 计划切分为</span>
<span class="w"> </span>-><span class="w"> </span>zqCoder<span class="w"> </span>
<span class="w"> </span>-><span class="w"> </span>zqSMM
$<span class="w"> </span>ls<span class="w"> </span>ZqFLOSS/data/<span class="w"> </span><span class="p">|</span><span class="w"> </span>wc
<span class="w"> </span><span class="m">30767</span><span class="w"> </span><span class="m">30767</span><span class="w"> </span><span class="m">461505</span>
<span class="c1"># 计划切分为</span>
<span class="w"> </span>-><span class="w"> </span>zqDevRes
<span class="w"> </span>-><span class="w"> </span>zqSCM<span class="w"> </span>
<span class="w"> </span>-><span class="w"> </span>zqPythonic
</code></pre></div>
<p>先在仓库中,根据拆分目标,将内容树收纳到对应的目录中,
以便复制,加载后,快速删除.</p>
<h4 id="pax">pax<a class="headerlink" href="#pax" title="Permanent link">¶</a></h4>
<p><code>pax</code> 是个好工具,原先习惯性的用 <code>cp</code> 那叫个慢!
搜索才知道,大量小文件的迁移就应该用 <code>pax</code>
于是简单的起个背景周末跑吧....</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>du<span class="w"> </span>-hs<span class="w"> </span>*
...
<span class="m">5</span>.7G<span class="w"> </span>ZqDevRel
<span class="w"> </span><span class="m">5</span>.7G<span class="w"> </span>zqCoder
<span class="w"> </span><span class="m">5</span>.7G<span class="w"> </span>zqSMM
<span class="m">6</span>.5G<span class="w"> </span>ZqFLOSS
<span class="w"> </span><span class="m">6</span>.5G<span class="w"> </span>zqDevRes
<span class="w"> </span><span class="m">6</span>.5G<span class="w"> </span>zqPythonic
<span class="w"> </span><span class="m">6</span>.5G<span class="w"> </span>zqSCM
...
<span class="m">4</span>.0K<span class="w"> </span>scraptools
...
</code></pre></div>
<p>体积占用激增3倍!</p>
<p>然后,逐一用 ScrapBook 加载新的目录</p>
<h4 id="_7">手工删除目录树<a class="headerlink" href="#_7" title="Permanent link">¶</a></h4>
<p>再对比几个仓库的体积:</p>
<div class="highlight"><pre><span></span><code>~/KuaiPan/zScrapBook
$ ls ZqFLOSS/data/ | wc -l
30767
$ ls zqSCM/data/ | wc -l
25320
$ du -hs *
...
5.3G data
...
~/KuaiPan/zScrapBook
$ ls zqDevRes/data/ | wc -l
24045
$ ls zqPythonic/data/ | wc -l
24294
$ ls zqSCM/data/ | wc -l
25319
</code></pre></div>
<h4 id="_8">严正的不科学!<a class="headerlink" href="#_8" title="Permanent link">¶</a></h4>
<p>手工折腾了半天,却发现几乎没有释放多少空间出来,
好象总是有 20000 左右的目录,是不存在的页面节点...</p>
<h3 id="_9">解析<a class="headerlink" href="#_9" title="Permanent link">¶</a></h3>
<p>首先,</p>
<h3 id="_10">重构<a class="headerlink" href="#_10" title="Permanent link">¶</a></h3>
<p><a href="https://github.com/martinblech/xmltodict/issues/14">xml containing 1 child · Issue #14 · martinblech/xmltodict</a></p>
<p><code>dict_constructor</code></p>
<h3 id="_11">删除<a class="headerlink" href="#_11" title="Permanent link">¶</a></h3>
<h2 id="_12">回顾<a class="headerlink" href="#_12" title="Permanent link">¶</a></h2>
<p>JS 在 FireFox 的确不给力哪...</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>du<span class="w"> </span>-hs<span class="w"> </span>*
...
957M<span class="w"> </span>ZqDevRel
866M<span class="w"> </span>ZqFLOSS
349M<span class="w"> </span>ZqKss
<span class="m">3</span>.4G<span class="w"> </span>ZqSKM
...
<span class="m">1</span>.0G<span class="w"> </span>_chaos
<span class="m">5</span>.2G<span class="w"> </span>_stuff
...
424K<span class="w"> </span>scrapbooktools
766M<span class="w"> </span>zqCoder
<span class="m">1</span>.0G<span class="w"> </span>zqDevRes
<span class="m">1</span>.4G<span class="w"> </span>zqPythonic
<span class="m">1</span>.4G<span class="w"> </span>zqSCM
564M<span class="w"> </span>zqSMM
</code></pre></div>
<p>为什么,在 700M 的 zqCoder 仓库中无法搜索,但是, 3.4G 的ZqSKM 中就可以?!</p>
<p>认真对比,从重建的空仓库的 .rdf 中,发现:</p>
<div class="highlight"><pre><span></span><code><span class="nt"><RDF:Seq</span><span class="w"> </span><span class="na">RDF:about=</span><span class="s">"urn:scrapbook:search"</span><span class="nt">></span>
....
<span class="nt"></RDF:Seq></span>
</code></pre></div>
<p>这个节点中包含有意外的几万条记录!</p>
<div class="highlight"><pre><span></span><code><span class="k">for</span><span class="w"> </span><span class="n">seq</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">doc</span><span class="o">[</span><span class="n">'RDF:RDF'</span><span class="o">][</span><span class="n">'RDF:Seq'</span><span class="o">]</span><span class="err">:</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="s1">'urn:scrapbook:search'</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">seq</span><span class="o">[</span><span class="n">'@RDF:about'</span><span class="o">]</span><span class="err">:</span>
<span class="w"> </span><span class="n">seq</span><span class="p">.</span><span class="n">pop</span><span class="p">(</span><span class="s1">'RDF:li'</span><span class="p">)</span>
<span class="w"> </span><span class="k">break</span>
</code></pre></div>
<p>几行代码解决!</p>
<h3 id="_13">数据新结构<a class="headerlink" href="#_13" title="Permanent link">¶</a></h3>
<h3 id="_14">功能开关<a class="headerlink" href="#_14" title="Permanent link">¶</a></h3>
<h2 id="_15">时间帐单<a class="headerlink" href="#_15" title="Permanent link">¶</a></h2>
<div class="highlight"><pre><span></span><code>+ 3.5H 用pax 复制,手工清除多余树
+ 1.5H 重新理解自个儿的脚本,加载自制数据结构到湿件
+ 1.0H 追加走查功能
+ 2.0H 调试走查,优化输出,明确可清除无效节点的数量级
+ 1.5H 尝试用 click 改进功能开关,未果
+ 2.0H 对比测试不同的解析库
+ 1.0H 用xmltodict 重构原先的 走查功能
+ 1.5H 根据比对的需求,改进 xmltodict 的数据结构,追加 K/V 复用
+ 2.0H 再复制测试仓库,用 sh 小心的测试实际删除行为
+ 1.0H 通测
+ 2.5H 批量处置7 个新旧仓库,清删除 16万+ 个无用目标, 近25G+ 空间释放
+ 4.0H 整理代码, 组织文档
24.5H+ 自然时间, 3+天业余时间
</code></pre></div>
<ul>
<li>140909 才算完成一个可以看的版本</li>
<li>140711 完成所有功能,启动文档回顾</li>
</ul>
<h1 id="140708-scrapbook">140708 ScrapBook 分库<a class="headerlink" href="#140708-scrapbook" title="Permanent link">¶</a></h1>
<h2 id="2h-click">+2H click<a class="headerlink" href="#2h-click" title="Permanent link">¶</a></h2>
<p>果然,清查出有大量, FLOSS 中当初没有合理清除的节点
从 ROOT 引发的树中挂不上的</p>
<h2 id="2h">+2H 实际清减<a class="headerlink" href="#2h" title="Permanent link">¶</a></h2>
<p><a href="http://amoffat.github.io/sh/">sh 1.08 — sh v1.08 documentation</a></p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">sh</span> <span class="kn">import</span> <span class="n">rm</span>
<span class="o">...</span>
<span class="nb">print</span><span class="p">(</span><span class="n">rm</span><span class="p">(</span><span class="s2">"-Rfv"</span><span class="p">,</span> <span class="n">del_dir</span><span class="p">))</span>
</code></pre></div>
<ul>
<li>用 sh 删除目录</li>
</ul>
<p>:</p>
<div class="highlight"><pre><span></span><code> tree_nodes: 3574
exp_items: 4164
dirs: 590
DESC : 24190
chaos: 20616
有效: 3574
$ ls reDevRel/data/ | wc -l
2996
</code></pre></div>
<ul>
<li>用 lxml/模板 重构 rdf</li>
</ul>
<p>人肉来总是感觉不对,</p>
<p>尝试:</p>
<h3 id="lxml">lxml<a class="headerlink" href="#lxml" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code>忒复杂!!!
</code></pre></div>
<h3 id="untangle">untangle<a class="headerlink" href="#untangle" title="Permanent link">¶</a></h3>
<p><a href="https://github.com/stchris/untangle">stchris/untangle</a></p>
<div class="highlight"><pre><span></span><code><span class="n">RDF</span><span class="o">:</span><span class="n">Seq</span><span class="w"> </span><span class="mi">579</span>
<span class="n">RDF_Description</span><span class="w"> </span><span class="mi">24190</span>
<span class="n">NC</span><span class="o">:</span><span class="n">BookmarkSeparator</span><span class="w"> </span><span class="mi">57</span>
<span class="o"><</span><span class="n">open</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="s1">'_chaos/scraotools_reDevRel.pkl'</span><span class="o">,</span><span class="w"> </span><span class="n">mode</span><span class="w"> </span><span class="s1">'wb'</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="mh">0x100666ed0</span><span class="o">></span>
<span class="w"> </span><span class="n">exp_level_idx</span><span class="o">()</span><span class="w"> </span><span class="n">RUNed</span><span class="o">~</span><span class="w"> </span><span class="mf">2263.57079</span><span class="w"> </span><span class="n">ms</span>
</code></pre></div>
<p>快,但是,无法Dump,而且书写不直觉, 要将 ":" 变成 "_"
obj.RDF_RDF.RDF_Description</p>
<div class="highlight"><pre><span></span><code><span class="o"><</span><span class="n">open</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="s1">'_chaos/scraotools_reDevRel.pkl'</span><span class="p">,</span><span class="w"> </span><span class="n">mode</span><span class="w"> </span><span class="s1">'wb'</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="mh">0x100769ed0</span><span class="o">></span>
<span class="n">Traceback</span><span class="w"> </span><span class="p">(</span><span class="n">most</span><span class="w"> </span><span class="n">recent</span><span class="w"> </span><span class="n">call</span><span class="w"> </span><span class="n">last</span><span class="p">):</span>
<span class="w"> </span><span class="n">File</span><span class="w"> </span><span class="s2">"scraptools/zq_chk4scrap.py"</span><span class="p">,</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="mi">457</span><span class="p">,</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="w"> </span><span class="n">RDFD</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">exp_level_idx</span><span class="p">(</span><span class="n">MYBOOK</span><span class="p">)</span>
<span class="w"> </span><span class="n">File</span><span class="w"> </span><span class="s2">"scraptools/zq_chk4scrap.py"</span><span class="p">,</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="mi">161</span><span class="p">,</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">cal_time</span>
<span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">func</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="w"> </span><span class="n">File</span><span class="w"> </span><span class="s2">"scraptools/zq_chk4scrap.py"</span><span class="p">,</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="mi">205</span><span class="p">,</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">exp_level_idx</span>
<span class="w"> </span><span class="n">pickle</span><span class="o">.</span><span class="n">dump</span><span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">RDF_RDF</span><span class="p">,</span><span class="w"> </span><span class="n">output</span><span class="p">)</span>
<span class="w"> </span><span class="n">File</span><span class="w"> </span><span class="s2">"/Users/zoomq/.pyenv/versions/2.7.6/lib/python2.7/pickle.py"</span><span class="p">,</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="mi">1370</span><span class="p">,</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">dump</span>
<span class="w"> </span><span class="n">Pickler</span><span class="p">(</span><span class="n">file</span><span class="p">,</span><span class="w"> </span><span class="n">protocol</span><span class="p">)</span><span class="o">.</span><span class="n">dump</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span>
<span class="w"> </span><span class="n">File</span><span class="w"> </span><span class="s2">"/Users/zoomq/.pyenv/versions/2.7.6/lib/python2.7/pickle.py"</span><span class="p">,</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="mi">224</span><span class="p">,</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">dump</span>
<span class="w"> </span><span class="bp">self</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span>
<span class="w"> </span><span class="n">File</span><span class="w"> </span><span class="s2">"/Users/zoomq/.pyenv/versions/2.7.6/lib/python2.7/pickle.py"</span><span class="p">,</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="mi">286</span><span class="p">,</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">save</span>
<span class="w"> </span><span class="n">f</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">obj</span><span class="p">)</span><span class="w"> </span><span class="c1"># Call unbound method with explicit self</span>
<span class="w"> </span><span class="n">File</span><span class="w"> </span><span class="s2">"/Users/zoomq/.pyenv/versions/2.7.6/lib/python2.7/pickle.py"</span><span class="p">,</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="mi">719</span><span class="p">,</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">save_inst</span>
<span class="w"> </span><span class="n">getstate</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">obj</span><span class="o">.</span><span class="n">__getstate__</span>
<span class="w"> </span><span class="n">File</span><span class="w"> </span><span class="s2">"/Users/zoomq/.pyenv/versions/276chaos/lib/python2.7/site-packages/untangle.py"</span><span class="p">,</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="mi">66</span><span class="p">,</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">__getattr__</span>
<span class="w"> </span><span class="n">raise</span><span class="w"> </span><span class="n">IndexError</span><span class="p">(</span><span class="s1">'Unknown key <</span><span class="si">%s</span><span class="s1">>'</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="n">key</span><span class="p">)</span>
<span class="n">IndexError</span><span class="p">:</span><span class="w"> </span><span class="n">Unknown</span><span class="w"> </span><span class="n">key</span><span class="w"> </span><span class="o"><</span><span class="n">__getstate__</span><span class="o">></span>
</code></pre></div>
<h3 id="xmltodict">xmltodict<a class="headerlink" href="#xmltodict" title="Permanent link">¶</a></h3>
<p><a href="https://github.com/martinblech/xmltodict">martinblech/xmltodict</a></p>
<div class="highlight"><pre><span></span><code><span class="k">[u'RDF:RDF']</span>
<span class="na">RDF</span><span class="o">:</span><span class="s">Seq 579</span>
<span class="na">RDF</span><span class="o">:</span><span class="s">Description 24190</span>
<span class="na">NC</span><span class="o">:</span><span class="s">BookmarkSeparator 57</span>
<span class="w"> </span><span class="na">exp_level_idx() RUNed~ 4997.31612 ms</span>
</code></pre></div>
<p>慢,但是,能 dump 而且书写直觉
doc['RDF:RDF']['RDF:Seq']</p>
<div class="highlight"><pre><span></span><code><span class="k">[u'RDF:RDF']</span>
<span class="na">RDF</span><span class="o">:</span><span class="s">Seq 579</span>
<span class="na">RDF</span><span class="o">:</span><span class="s">Description 24190</span>
<span class="na">NC</span><span class="o">:</span><span class="s">BookmarkSeparator 57</span>
<span class="na"><open file '_chaos/scraotools_reDevRel.pkl', mode 'wb' at 0x10f26d420></span>
<span class="w"> </span><span class="na">exp_level_idx() RUNed~ 16878.75390 ms</span>
</code></pre></div>
<p>同时,能反写出XML 来!</p>
<p>主要问题是行为不统一!</p>
<div class="highlight"><pre><span></span><code><span class="nt"><RDF:Seq</span><span class="w"> </span><span class="na">RDF:about=</span><span class="s">"urn:scrapbook:item20070113201921"</span><span class="nt">></span>
<span class="w"> </span><span class="nt"><RDF:li</span><span class="w"> </span><span class="na">RDF:resource=</span><span class="s">"urn:scrapbook:item20070113201940"</span><span class="nt">/></span>
<span class="w"> </span><span class="nt"><RDF:li</span><span class="w"> </span><span class="na">RDF:resource=</span><span class="s">"urn:scrapbook:item20070113201941"</span><span class="nt">/></span>
<span class="nt"></RDF:Seq></span>
</code></pre></div>
<p>时 唯一的 RDF:Li 不是 List!!</p>
<div class="highlight"><pre><span></span><code><span class="n">K2SEQ</span><span class="o">[</span><span class="n">crt_id</span><span class="o">]></span><span class="nl">RDF</span><span class="p">:</span><span class="n">Li</span><span class="w"> </span><span class="n">OrderedDict</span><span class="p">(</span><span class="o">[</span><span class="n">(u'@RDF:resource', u'urn:scrapbook:item20070113201921')</span><span class="o">]</span><span class="p">)</span>
<span class="n">K2SEQ</span><span class="o">[</span><span class="n">crt_id</span><span class="o">][</span><span class="n">'RDF:li'</span><span class="o">]</span><span class="p">.</span><span class="nf">len</span><span class="o">::</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="o"><</span><span class="k">class</span><span class="w"> </span><span class="s1">'collections.OrderedDict'</span><span class="o">></span>
<span class="n">K2SEQ</span><span class="o">[</span><span class="n">crt_id</span><span class="o">]></span><span class="nl">RDF</span><span class="p">:</span><span class="n">Li</span><span class="w"> </span><span class="nv">@RDF</span><span class="err">:</span><span class="n">resource</span>
<span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="n">crt_node</span><span class="p">.</span><span class="nl">keys</span><span class="p">:</span>
<span class="nv">@RDF</span><span class="err">:</span><span class="n">resource</span>
<span class="n">K2SEQ</span><span class="o">[</span><span class="n">crt_id</span><span class="o">]></span><span class="nl">RDF</span><span class="p">:</span><span class="n">Li</span><span class="w"> </span><span class="n">OrderedDict</span><span class="p">(</span><span class="o">[</span><span class="n">(u'@RDF:resource', u'urn:scrapbook:item20070527160000')</span><span class="o">]</span><span class="p">)</span>
<span class="o">~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span>
<span class="n">K2SEQ</span><span class="o">[</span><span class="n">crt_id</span><span class="o">]></span><span class="nl">RDF</span><span class="p">:</span><span class="n">Li</span><span class="w"> </span><span class="n">OrderedDict</span><span class="p">(</span><span class="o">[</span><span class="n">(u'@RDF:resource', u'urn:scrapbook:item20061006133550')</span><span class="o">]</span><span class="p">)</span>
<span class="n">K2SEQ</span><span class="o">[</span><span class="n">crt_id</span><span class="o">][</span><span class="n">'RDF:li'</span><span class="o">]</span><span class="p">.</span><span class="nf">len</span><span class="o">::</span><span class="w"> </span><span class="mi">9</span>
<span class="w"> </span><span class="o"><</span><span class="n">type</span><span class="w"> </span><span class="s1">'list'</span><span class="o">></span>
</code></pre></div>
<p><a href="https://github.com/martinblech/xmltodict/issues/67">odd parse for same xml structure · Issue #67 · martinblech/xmltodict</a></p>
<h3 id="4h">4H 折腾明白了:<a class="headerlink" href="#4h" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code><span class="o">$</span><span class="w"> </span><span class="n">python</span><span class="w"> </span><span class="n">scraptools</span><span class="o">/</span><span class="n">zq_chk4scrap</span><span class="o">.</span><span class="n">py</span><span class="w"> </span><span class="n">reDevRel</span><span class="o">/</span>
<span class="o">/</span><span class="n">Users</span><span class="o">/</span><span class="n">zoomq</span><span class="o">/</span><span class="n">mnt</span><span class="o">/</span><span class="err">快盘</span><span class="o">/</span><span class="n">zScrapBook</span><span class="o">/</span><span class="n">reDevRel</span><span class="o">/</span><span class="n">scrapbook</span><span class="o">.</span><span class="n">rdf</span>
<span class="p">[</span><span class="sa">u</span><span class="s1">'RDF:RDF'</span><span class="p">]</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">Seq</span><span class="w"> </span><span class="mi">579</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">Description</span><span class="w"> </span><span class="mi">24190</span>
<span class="n">NC</span><span class="p">:</span><span class="n">BookmarkSeparator</span><span class="w"> </span><span class="mi">57</span>
<span class="o"><</span><span class="n">open</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="s1">'_chaos/scraotools_reDevRel.pkl'</span><span class="p">,</span><span class="w"> </span><span class="n">mode</span><span class="w"> </span><span class="s1">'wb'</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="mh">0x10f17a660</span><span class="o">></span>
<span class="w"> </span><span class="n">exp_level_idx</span><span class="p">()</span><span class="w"> </span><span class="n">RUNed</span><span class="o">~</span><span class="w"> </span><span class="mf">17073.48084</span><span class="w"> </span><span class="n">ms</span>
<span class="n">_chaos</span><span class="o">/</span><span class="n">scraotools_reDevRel</span><span class="o">.</span><span class="n">pkl</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">ROOT</span><span class="w"> </span><span class="mi">13</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">Seq</span><span class="w"> </span><span class="mi">578</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">Description</span><span class="w"> </span><span class="mi">24190</span>
<span class="n">NC</span><span class="p">:</span><span class="n">BookmarkSeparator</span><span class="w"> </span><span class="mi">57</span>
<span class="w"> </span><span class="n">_load_pkl</span><span class="p">()</span><span class="w"> </span><span class="n">RUNed</span><span class="o">~</span><span class="w"> </span><span class="mf">7872.95103</span><span class="w"> </span><span class="n">ms</span>
<span class="w"> </span><span class="n">_RIGHT_NODES</span><span class="p">:</span><span class="w"> </span><span class="mi">6926</span>
<span class="w"> </span><span class="n">RIGHT_NODES</span><span class="p">:</span><span class="w"> </span><span class="mi">3631</span>
<span class="w"> </span><span class="n">re_xmltodict_rdf</span><span class="p">()</span><span class="w"> </span><span class="n">RUNed</span><span class="o">~</span><span class="w"> </span><span class="mf">191.21003</span><span class="w"> </span><span class="n">ms</span>
</code></pre></div>
<p>有这么多垃圾!</p>
<div class="highlight"><pre><span></span><code><span class="mf">24190</span><span class="w"> </span><span class="n">vs</span><span class="w"> </span><span class="mf">3631</span><span class="w"> </span><span class="err">!!!!</span>
</code></pre></div>
<p>但是,居然无法一次性清理干净?!</p>
<p>一扫::</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>python<span class="w"> </span>scraptools/zq_chk4scrap.py<span class="w"> </span>reDevRel/
/Users/zoomq/mnt/快盘/zScrapBook/reDevRel/scrapbook.rdf
<span class="o">[</span>u<span class="s1">'RDF:RDF'</span><span class="o">]</span>
RDF:Seq<span class="w"> </span><span class="m">579</span>
RDF:Description<span class="w"> </span><span class="m">24190</span>
NC:BookmarkSeparator<span class="w"> </span><span class="m">57</span>
<open<span class="w"> </span>file<span class="w"> </span><span class="s1">'_chaos/scraotools_reDevRel.pkl'</span>,<span class="w"> </span>mode<span class="w"> </span><span class="s1">'wb'</span><span class="w"> </span>at<span class="w"> </span>0x10f2376f0>
<span class="w"> </span>exp_level_idx<span class="o">()</span><span class="w"> </span>RUNed~<span class="w"> </span><span class="m">17013</span>.92913<span class="w"> </span>ms
<span class="w"> </span>_RIGHT_NODES:<span class="w"> </span><span class="m">6926</span>
<span class="w"> </span>RIGHT_NODES:<span class="w"> </span><span class="m">3631</span>
clean<span class="w"> </span>notes:<span class="w"> </span><span class="m">11153</span>
cleanned<span class="w"> </span>DESC:<span class="w"> </span><span class="m">13037</span>
<open<span class="w"> </span>file<span class="w"> </span><span class="s1">'_chaos/scraotools_reDevRel.pkl'</span>,<span class="w"> </span>mode<span class="w"> </span><span class="s1">'wb'</span><span class="w"> </span>at<span class="w"> </span>0x10eecff60>
_chaos/scrapbook_reDevRel.rdf
<span class="w"> </span>re_xmltodict_rdf<span class="o">()</span><span class="w"> </span>RUNed~<span class="w"> </span><span class="m">131239</span>.34913<span class="w"> </span>ms
</code></pre></div>
<p>2扫:</p>
<div class="highlight"><pre><span></span><code><span class="o">$</span><span class="w"> </span><span class="n">python</span><span class="w"> </span><span class="n">scraptools</span><span class="o">/</span><span class="n">zq_chk4scrap</span><span class="o">.</span><span class="n">py</span><span class="w"> </span><span class="n">reDevRel</span><span class="o">/</span>
<span class="n">_chaos</span><span class="o">/</span><span class="n">scraotools_reDevRel</span><span class="o">.</span><span class="n">pkl</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">ROOT</span><span class="w"> </span><span class="mi">13</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">Seq</span><span class="w"> </span><span class="mi">578</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">Description</span><span class="w"> </span><span class="mi">13037</span>
<span class="n">NC</span><span class="p">:</span><span class="n">BookmarkSeparator</span><span class="w"> </span><span class="mi">57</span>
<span class="w"> </span><span class="n">_load_pkl</span><span class="p">()</span><span class="w"> </span><span class="n">RUNed</span><span class="o">~</span><span class="w"> </span><span class="mf">4292.33599</span><span class="w"> </span><span class="n">ms</span>
<span class="w"> </span><span class="n">_RIGHT_NODES</span><span class="p">:</span><span class="w"> </span><span class="mi">6926</span>
<span class="w"> </span><span class="n">RIGHT_NODES</span><span class="p">:</span><span class="w"> </span><span class="mi">3631</span>
<span class="n">clean</span><span class="w"> </span><span class="n">notes</span><span class="p">:</span><span class="w"> </span><span class="mi">5506</span>
<span class="n">cleanned</span><span class="w"> </span><span class="n">DESC</span><span class="p">:</span><span class="w"> </span><span class="mi">7531</span>
<span class="o"><</span><span class="n">open</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="s1">'_chaos/scraotools_reDevRel.pkl'</span><span class="p">,</span><span class="w"> </span><span class="n">mode</span><span class="w"> </span><span class="s1">'wb'</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="mh">0x108874f60</span><span class="o">></span>
<span class="n">_chaos</span><span class="o">/</span><span class="n">scrapbook_reDevRel</span><span class="o">.</span><span class="n">rdf</span>
<span class="w"> </span><span class="n">re_xmltodict_rdf</span><span class="p">()</span><span class="w"> </span><span class="n">RUNed</span><span class="o">~</span><span class="w"> </span><span class="mf">44531.90279</span><span class="w"> </span><span class="n">ms</span>
</code></pre></div>
<p>3扫::</p>
<div class="highlight"><pre><span></span><code><span class="o">$</span><span class="w"> </span><span class="n">python</span><span class="w"> </span><span class="n">scraptools</span><span class="o">/</span><span class="n">zq_chk4scrap</span><span class="o">.</span><span class="n">py</span><span class="w"> </span><span class="n">reDevRel</span><span class="o">/</span>
<span class="n">_chaos</span><span class="o">/</span><span class="n">scraotools_reDevRel</span><span class="o">.</span><span class="n">pkl</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">ROOT</span><span class="w"> </span><span class="mi">13</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">Seq</span><span class="w"> </span><span class="mi">578</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">Description</span><span class="w"> </span><span class="mi">7531</span>
<span class="n">NC</span><span class="p">:</span><span class="n">BookmarkSeparator</span><span class="w"> </span><span class="mi">57</span>
<span class="w"> </span><span class="n">_load_pkl</span><span class="p">()</span><span class="w"> </span><span class="n">RUNed</span><span class="o">~</span><span class="w"> </span><span class="mf">3115.18502</span><span class="w"> </span><span class="n">ms</span>
<span class="w"> </span><span class="n">_RIGHT_NODES</span><span class="p">:</span><span class="w"> </span><span class="mi">6926</span>
<span class="w"> </span><span class="n">RIGHT_NODES</span><span class="p">:</span><span class="w"> </span><span class="mi">3631</span>
<span class="n">clean</span><span class="w"> </span><span class="n">notes</span><span class="p">:</span><span class="w"> </span><span class="mi">2616</span>
<span class="n">cleanned</span><span class="w"> </span><span class="n">DESC</span><span class="p">:</span><span class="w"> </span><span class="mi">4915</span>
<span class="o"><</span><span class="n">open</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="s1">'_chaos/scraotools_reDevRel.pkl'</span><span class="p">,</span><span class="w"> </span><span class="n">mode</span><span class="w"> </span><span class="s1">'wb'</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="mh">0x105d1edb0</span><span class="o">></span>
<span class="n">_chaos</span><span class="o">/</span><span class="n">scrapbook_reDevRel</span><span class="o">.</span><span class="n">rdf</span>
<span class="w"> </span><span class="n">re_xmltodict_rdf</span><span class="p">()</span><span class="w"> </span><span class="n">RUNed</span><span class="o">~</span><span class="w"> </span><span class="mf">19026.94511</span><span class="w"> </span><span class="n">ms</span>
</code></pre></div>
<p>4扫::</p>
<div class="highlight"><pre><span></span><code><span class="o">$</span><span class="w"> </span><span class="n">python</span><span class="w"> </span><span class="n">scraptools</span><span class="o">/</span><span class="n">zq_chk4scrap</span><span class="o">.</span><span class="n">py</span><span class="w"> </span><span class="n">reDevRel</span><span class="o">/</span>
<span class="n">_chaos</span><span class="o">/</span><span class="n">scraotools_reDevRel</span><span class="o">.</span><span class="n">pkl</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">ROOT</span><span class="w"> </span><span class="mi">13</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">Seq</span><span class="w"> </span><span class="mi">578</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">Description</span><span class="w"> </span><span class="mi">4915</span>
<span class="n">NC</span><span class="p">:</span><span class="n">BookmarkSeparator</span><span class="w"> </span><span class="mi">57</span>
<span class="w"> </span><span class="n">_load_pkl</span><span class="p">()</span><span class="w"> </span><span class="n">RUNed</span><span class="o">~</span><span class="w"> </span><span class="mf">2528.49293</span><span class="w"> </span><span class="n">ms</span>
<span class="w"> </span><span class="n">_RIGHT_NODES</span><span class="p">:</span><span class="w"> </span><span class="mi">6926</span>
<span class="w"> </span><span class="n">RIGHT_NODES</span><span class="p">:</span><span class="w"> </span><span class="mi">3631</span>
<span class="n">clean</span><span class="w"> </span><span class="n">notes</span><span class="p">:</span><span class="w"> </span><span class="mi">1045</span>
<span class="n">cleanned</span><span class="w"> </span><span class="n">DESC</span><span class="p">:</span><span class="w"> </span><span class="mi">3870</span>
<span class="o"><</span><span class="n">open</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="s1">'_chaos/scraotools_reDevRel.pkl'</span><span class="p">,</span><span class="w"> </span><span class="n">mode</span><span class="w"> </span><span class="s1">'wb'</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="mh">0x10429ced0</span><span class="o">></span>
<span class="n">_chaos</span><span class="o">/</span><span class="n">scrapbook_reDevRel</span><span class="o">.</span><span class="n">rdf</span>
<span class="w"> </span><span class="n">re_xmltodict_rdf</span><span class="p">()</span><span class="w"> </span><span class="n">RUNed</span><span class="o">~</span><span class="w"> </span><span class="mf">11538.43212</span><span class="w"> </span><span class="n">ms</span>
</code></pre></div>
<p>5扫:</p>
<div class="highlight"><pre><span></span><code><span class="o">$</span><span class="w"> </span><span class="n">python</span><span class="w"> </span><span class="n">scraptools</span><span class="o">/</span><span class="n">zq_chk4scrap</span><span class="o">.</span><span class="n">py</span><span class="w"> </span><span class="n">reDevRel</span><span class="o">/</span>
<span class="n">_chaos</span><span class="o">/</span><span class="n">scraotools_reDevRel</span><span class="o">.</span><span class="n">pkl</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">ROOT</span><span class="w"> </span><span class="mi">13</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">Seq</span><span class="w"> </span><span class="mi">578</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">Description</span><span class="w"> </span><span class="mi">3870</span>
<span class="n">NC</span><span class="p">:</span><span class="n">BookmarkSeparator</span><span class="w"> </span><span class="mi">57</span>
<span class="w"> </span><span class="n">_load_pkl</span><span class="p">()</span><span class="w"> </span><span class="n">RUNed</span><span class="o">~</span><span class="w"> </span><span class="mf">2422.85681</span><span class="w"> </span><span class="n">ms</span>
<span class="w"> </span><span class="n">_RIGHT_NODES</span><span class="p">:</span><span class="w"> </span><span class="mi">6926</span>
<span class="w"> </span><span class="n">RIGHT_NODES</span><span class="p">:</span><span class="w"> </span><span class="mi">3631</span>
<span class="n">clean</span><span class="w"> </span><span class="n">notes</span><span class="p">:</span><span class="w"> </span><span class="mi">286</span>
<span class="n">cleanned</span><span class="w"> </span><span class="n">DESC</span><span class="p">:</span><span class="w"> </span><span class="mi">3584</span>
<span class="o"><</span><span class="n">open</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="s1">'_chaos/scraotools_reDevRel.pkl'</span><span class="p">,</span><span class="w"> </span><span class="n">mode</span><span class="w"> </span><span class="s1">'wb'</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="mh">0x102c5d300</span><span class="o">></span>
<span class="n">_chaos</span><span class="o">/</span><span class="n">scrapbook_reDevRel</span><span class="o">.</span><span class="n">rdf</span>
<span class="w"> </span><span class="n">re_xmltodict_rdf</span><span class="p">()</span><span class="w"> </span><span class="n">RUNed</span><span class="o">~</span><span class="w"> </span><span class="mf">9368.47901</span><span class="w"> </span><span class="n">ms</span>
</code></pre></div>
<p>6扫::</p>
<div class="highlight"><pre><span></span><code><span class="o">$</span><span class="w"> </span><span class="n">python</span><span class="w"> </span><span class="n">scraptools</span><span class="o">/</span><span class="n">zq_chk4scrap</span><span class="o">.</span><span class="n">py</span><span class="w"> </span><span class="n">reDevRel</span><span class="o">/</span>
<span class="n">_chaos</span><span class="o">/</span><span class="n">scraotools_reDevRel</span><span class="o">.</span><span class="n">pkl</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">ROOT</span><span class="w"> </span><span class="mi">13</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">Seq</span><span class="w"> </span><span class="mi">578</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">Description</span><span class="w"> </span><span class="mi">3584</span>
<span class="n">NC</span><span class="p">:</span><span class="n">BookmarkSeparator</span><span class="w"> </span><span class="mi">57</span>
<span class="w"> </span><span class="n">_load_pkl</span><span class="p">()</span><span class="w"> </span><span class="n">RUNed</span><span class="o">~</span><span class="w"> </span><span class="mf">2225.17014</span><span class="w"> </span><span class="n">ms</span>
<span class="w"> </span><span class="n">_RIGHT_NODES</span><span class="p">:</span><span class="w"> </span><span class="mi">6926</span>
<span class="w"> </span><span class="n">RIGHT_NODES</span><span class="p">:</span><span class="w"> </span><span class="mi">3631</span>
<span class="n">clean</span><span class="w"> </span><span class="n">notes</span><span class="p">:</span><span class="w"> </span><span class="mi">10</span>
<span class="n">cleanned</span><span class="w"> </span><span class="n">DESC</span><span class="p">:</span><span class="w"> </span><span class="mi">3574</span>
<span class="o"><</span><span class="n">open</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="s1">'_chaos/scraotools_reDevRel.pkl'</span><span class="p">,</span><span class="w"> </span><span class="n">mode</span><span class="w"> </span><span class="s1">'wb'</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="mh">0x102c2af60</span><span class="o">></span>
<span class="n">_chaos</span><span class="o">/</span><span class="n">scrapbook_reDevRel</span><span class="o">.</span><span class="n">rdf</span>
<span class="w"> </span><span class="n">re_xmltodict_rdf</span><span class="p">()</span><span class="w"> </span><span class="n">RUNed</span><span class="o">~</span><span class="w"> </span><span class="mf">8464.92100</span><span class="w"> </span><span class="n">ms</span>
</code></pre></div>
<p>7扫:</p>
<div class="highlight"><pre><span></span><code><span class="o">$</span><span class="w"> </span><span class="n">python</span><span class="w"> </span><span class="n">scraptools</span><span class="o">/</span><span class="n">zq_chk4scrap</span><span class="o">.</span><span class="n">py</span><span class="w"> </span><span class="n">reDevRel</span><span class="o">/</span>
<span class="n">_chaos</span><span class="o">/</span><span class="n">scraotools_reDevRel</span><span class="o">.</span><span class="n">pkl</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">ROOT</span><span class="w"> </span><span class="mi">13</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">Seq</span><span class="w"> </span><span class="mi">578</span>
<span class="n">RDF</span><span class="p">:</span><span class="n">Description</span><span class="w"> </span><span class="mi">3574</span>
<span class="n">NC</span><span class="p">:</span><span class="n">BookmarkSeparator</span><span class="w"> </span><span class="mi">57</span>
<span class="w"> </span><span class="n">_load_pkl</span><span class="p">()</span><span class="w"> </span><span class="n">RUNed</span><span class="o">~</span><span class="w"> </span><span class="mf">2317.77310</span><span class="w"> </span><span class="n">ms</span>
<span class="w"> </span><span class="n">_RIGHT_NODES</span><span class="p">:</span><span class="w"> </span><span class="mi">6926</span>
<span class="w"> </span><span class="n">RIGHT_NODES</span><span class="p">:</span><span class="w"> </span><span class="mi">3631</span>
<span class="n">clean</span><span class="w"> </span><span class="n">notes</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span>
<span class="n">cleanned</span><span class="w"> </span><span class="n">DESC</span><span class="p">:</span><span class="w"> </span><span class="mi">3574</span>
<span class="o"><</span><span class="n">open</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="s1">'_chaos/scraotools_reDevRel.pkl'</span><span class="p">,</span><span class="w"> </span><span class="n">mode</span><span class="w"> </span><span class="s1">'wb'</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="mh">0x1021b3030</span><span class="o">></span>
<span class="n">_chaos</span><span class="o">/</span><span class="n">scrapbook_reDevRel</span><span class="o">.</span><span class="n">rdf</span>
<span class="w"> </span><span class="n">re_xmltodict_rdf</span><span class="p">()</span><span class="w"> </span><span class="n">RUNed</span><span class="o">~</span><span class="w"> </span><span class="mf">8694.52500</span><span class="w"> </span><span class="n">ms</span>
</code></pre></div>
<h3 id="2">2小时 目录对比<a class="headerlink" href="#2" title="Permanent link">¶</a></h3>
<p>sh->ls 出来时,</p>
<p>是 STDOUT 有隐藏字符!
兰色...居然没有意识到!</p>
<div class="highlight"><pre><span></span><code><span class="mf">20041214101930</span>
<span class="o"><</span><span class="n">type</span><span class="w"> </span><span class="err">'</span><span class="n">str</span><span class="err">'</span><span class="o">></span>
<span class="n">Traceback</span><span class="w"> </span><span class="p">(</span><span class="n">most</span><span class="w"> </span><span class="n">recent</span><span class="w"> </span><span class="n">call</span><span class="w"> </span><span class="n">last</span><span class="p">):</span>
<span class="w"> </span><span class="n">File</span><span class="w"> </span><span class="s">"scraptools/zq_chk4scrap.py"</span><span class="p">,</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="mf">724</span><span class="p">,</span><span class="w"> </span><span class="n">in</span><span class="w"> </span><span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="w"> </span><span class="n">mv_chaos_data</span><span class="p">(</span><span class="n">REPO_NAME</span><span class="p">,</span><span class="w"> </span><span class="n">XRDF</span><span class="p">)</span>
<span class="w"> </span><span class="n">File</span><span class="w"> </span><span class="s">"scraptools/zq_chk4scrap.py"</span><span class="p">,</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="mf">524</span><span class="p">,</span><span class="w"> </span><span class="n">in</span><span class="w"> </span><span class="n">mv_chaos_data</span>
<span class="w"> </span><span class="kr">print</span><span class="w"> </span><span class="nb">len</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">li</span><span class="p">))</span><span class="w"> </span><span class="err">#</span><span class="mf">.</span><span class="n">strip</span><span class="p">()</span>
<span class="nb">Val</span><span class="n">ueError</span><span class="p">:</span><span class="w"> </span><span class="n">invalid</span><span class="w"> </span><span class="n">literal</span><span class="w"> </span><span class="kr">for</span><span class="w"> </span><span class="nb">int</span><span class="p">()</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">base</span><span class="w"> </span><span class="mf">10</span><span class="p">:</span><span class="w"> </span><span class="err">'\</span><span class="n">x1b</span><span class="err">[</span><span class="mf">1</span><span class="n">m</span><span class="err">\</span><span class="n">x1b</span><span class="err">[</span><span class="mf">34</span><span class="n">m20041214101930</span><span class="err">\</span><span class="n">x1b</span><span class="err">[</span><span class="mf">39</span><span class="p">;</span><span class="mf">49</span><span class="n">m</span><span class="err">\</span><span class="n">x1b</span><span class="err">[</span><span class="mf">0</span><span class="n">m</span><span class="err">'</span>
</code></pre></div>
<h3 id="140710-1804">140710 18:04<a class="headerlink" href="#140710-1804" title="Permanent link">¶</a></h3>
<p>完成初步完备流程:</p>
<ul>
<li>从原始 scrapbook.rdf 读入为 Py 对象</li>
<li>模拟肉眼巡查, walk 出显示的合法内容数据集</li>
<li>加入其它辅助KV 节点,写为中间工作 .pkl</li>
<li>加载 工作 .pkl 到内存</li>
<li>对比原始 .rdf 数据中的节点和 walk 出来有效的,逐一清除无效的<ul>
<li>必须,尝试多次,直到清除干净</li>
<li>为毛...?</li>
</ul>
</li>
<li>对比实际目录和有效节点ID 的关系,将无效的,mv 到其它目录完成净化</li>
</ul>
<h2 id="todo">TODO<a class="headerlink" href="#todo" title="Permanent link">¶</a></h2>
<ul>
<li>解决反复清查的问题</li>
<li>提高效率</li>
</ul>
<p>:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>du<span class="w"> </span>-hs<span class="w"> </span>*
<span class="m">5</span>.1G<span class="w"> </span>ZqDevRel
950M<span class="w"> </span>reDevRel
<span class="w"> </span><span class="m">5</span>.2G<span class="w"> </span>zqCoder
<span class="w"> </span><span class="m">4</span>.9G<span class="w"> </span>zqSMM
<span class="m">8</span>.0M<span class="w"> </span>_chaos
<span class="m">4</span>.2G<span class="w"> </span>_stuff
<span class="m">6</span>.5G<span class="w"> </span>ZqFLOSS
<span class="w"> </span><span class="m">5</span>.2G<span class="w"> </span>zqDevRes
<span class="w"> </span><span class="m">5</span>.2G<span class="w"> </span>zqPythonic
<span class="w"> </span><span class="m">5</span>.3G<span class="w"> </span>zqSCM
<span class="m">3</span>.7G<span class="w"> </span>ZqSKM
</code></pre></div>pydata笔记:环境配置2014-06-03T00:00:00+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2014-06-03:/pydata-0-mavericks.html
<h2 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p><img alt="s27157694.jpg(JPEG 图像,300x300 像素)" src="http://img3.douban.com/lpic/s27157694.jpg"/></p>
<p><a href="http://book.douban.com/subject/25779298/">利用Python进行数据分析</a></p>
<p>是本好书...</p>
<p>为什么知道这书呢? 因为翻译 <a href="http://weekly.pychina.org/">|蠎周刊 |汇集全球蠎事儿 !-)</a></p>
<p>经常见到各种 Pandas 配合其它纯Python 模块折腾出来 …</p>
<h2 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p><img alt="s27157694.jpg(JPEG 图像,300x300 像素)" src="http://img3.douban.com/lpic/s27157694.jpg"/></p>
<p><a href="http://book.douban.com/subject/25779298/">利用Python进行数据分析</a></p>
<p>是本好书...</p>
<p>为什么知道这书呢? 因为翻译 <a href="http://weekly.pychina.org/">|蠎周刊 |汇集全球蠎事儿 !-)</a></p>
<p>经常见到各种 Pandas 配合其它纯Python 模块折腾出来的大数据可视化分析作品/文章,
而且从 <a href="http://book.douban.com/subject/7175280/">Python科学计算 (豆瓣)</a> 中很早
也知道了各种 Python 在数据分析方面的方便,
所以,一直想有机会能实战性的系统折腾一下...</p>
<p>这书当然注意到了,虽然不是 OBP 项目组织翻译的,
但是,好书就是好书,有点小贵,</p>
<p>最近有了台 GALAXY TAB3, 所以,能上 Kindle 了,于是,发现 z.cn 上电子书有了,
响应 @老赵的号召,立即收入!</p>
<h2 id="_2">探索<a class="headerlink" href="#_2" title="Permanent link">¶</a></h2>
<p>正如,Python 所有领域的自学,有一个稳定,随时有反馈的环境是最重要的...</p>
<p>但是,作者的话,真心不能都相信哪!</p>
<div class="highlight"><pre><span></span><code>...如果你恰好使用 Python 3.2 大部分示例是可以完整运行的
...
MAC OS X 环境推荐安装 epd_free-7.3-2-macosx-i386.dmg
...
</code></pre></div>
<p>于是...</p>
<h3 id="pyenv">pyenv<a class="headerlink" href="#pyenv" title="Permanent link">¶</a></h3>
<p>先尝试 Python 3.2 环境:</p>
<ul>
<li><code>$ pyenv install 3.2</code> 成功</li>
<li><code>$ pyenv virtualenv --distribute 3.2 32IPy</code></li>
<li><code>$ pyenc local 32IPy2</code> </li>
<li><code>$ pip install ipython</code>,成功</li>
<li><code>$ pip install pandas</code>, 失败</li>
</ul>
<p>然后回到书中作者的 2.7.3 环境,重新尝试</p>
<ul>
<li>一样败在 <code>$ pip install pandas</code></li>
<li>宏大的 <code>Matplotlib</code> 手工安装成功了的哪....</li>
</ul>
<h3 id="epd-free">EPD free<a class="headerlink" href="#epd-free" title="Permanent link">¶</a></h3>
<p>好吧,看来数据分析的系列模块也不是那么简单可以安装的,
所以,</p>
<p><a href="https://enthought.com/products/epd/free/">Enthought Python Distribution Free</a></p>
<p>嗯嗯嗯? </p>
<p><img alt="canopy-logo" src="https://enthought.com/static/img/canopy-logo.png"/></p>
<p>什么东西,不是说 <code>EPD free</code> 嘛?</p>
<p>直接搜索:</p>
<ul>
<li>epd_free-7.3-2-macosx-i386.dmg</li>
<li>果断还有: <a href="https://enthought.com/repo/free/">Index of /repo/free</a></li>
</ul>
<p>果断下载,安装...</p>
<p>各种不对味儿,原来自动在 <code>~/.bash_profile</code></p>
<div class="highlight"><pre><span></span><code><span class="c1"># Setting PATH for EPD_free-7.3-2</span>
<span class="c1"># The orginal version is saved in .bash_profile.pysave</span>
<span class="n">PATH</span><span class="o">=</span><span class="s2">"/Library/Frameworks/Python.framework/Versions/Current/bin:${PATH}"</span>
<span class="k">export</span><span class="w"> </span><span class="n">PATH</span>
</code></pre></div>
<p>而且是按照系统框架来安装到 <code>/Library/Frameworks/Python.framework</code> 的
可是, Mavericks 以后,没有默认Python 了哪,俺已经同时用 <code>brew</code> 管理系统 Python,
<code>pyenv</code> 管理开发 Python ,先不说体积:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>du<span class="w"> </span>-hs<span class="w"> </span>/Library/Frameworks/Python.framework/Versions
425M<span class="w"> </span>/Library/Frameworks/Python.framework/Versions
</code></pre></div>
<p>居然第一个案例就跑不起来!</p>
<p><code>import pandas</code> 有报错...</p>
<h3 id="canopy">Canopy<a class="headerlink" href="#canopy" title="Permanent link">¶</a></h3>
<p>回到官方下载: <a href="https://enthought.com/store/">Enthought Store</a></p>
<p>老老实实的下载推荐的 <code>canopy-1.4.0-osx-64.dmg</code>
体积也从 74M 爆涨为 <code>235Mb</code></p>
<p>不过,是一派标准的 MAC 软件包了,非常流畅,也有GUI 的引导界面,</p>
<p>然后 <code>~/.bash_profile</code> 追加的是:</p>
<div class="highlight"><pre><span></span><code><span class="gh">#</span> Added by Canopy installer on 2014-06-03
<span class="gh">#</span> VIRTUAL_ENV_DISABLE_PROMPT can be set to '' to make bashprompt show that Canopy is active, otherwise 1
VIRTUAL_ENV_DISABLE_PROMPT=1 source \
/Users/zoomq/Library/Enthought/Canopy_64bit/User/bin/activate
</code></pre></div>
<p>那就简单了,使用标准的 <code>VirtualEnv</code> 来包装的话,就不用将系统Python 环境永久性的迁移为
<code>Canopy</code> 的了,</p>
<p>简单的 在 <code>~/.bashrc</code> 定义一个别称:</p>
<div class="highlight"><pre><span></span><code><span class="gh">#</span> Added by Canopy installer on 2014-06-03
alias canopy="source \
/Users/zoomq/Library/Enthought/Canopy_64bit/User/bin/activate"
</code></pre></div>
<p>随时调用 <code>canopy</code> 就可以进入了..</p>
<h2 id="_3">结论<a class="headerlink" href="#_3" title="Permanent link">¶</a></h2>
<p>最终拥有了和书中有一致反应的环境:</p>
<p><img alt="140604-pydata-canopy.png" src="http://zoomq.qiniudn.com/ZQCollection/snap/140604-pydata-canopy.png"/></p>
<p>参考:</p>
<ul>
<li>
<p><a href="http://stackoverflow.com/questions/3819449/how-to-uninstall-python-2-7-on-a-mac-os-x-10-6-4">osx - How to uninstall Python 2.7 on a Mac OS X 10.6.4? - Stack Overflow</a></p>
<ul>
<li>sudo rm -rf /Library/Frameworks/Python.framework/Versions/2.7</li>
<li>sudo rm -rf "/Applications/Python 2.7"</li>
<li>remove the symbolic links in /usr/local/bin that point to this python version see ls -l /usr/local/bin</li>
</ul>
</li>
<li>
<p><a href="http://docs.python-guide.org/en/latest/starting/install/osx/">Installing Python on Mac OS X — The Hitchhiker's Guide to Python</a></p>
<ul>
<li><a href="http://wolfpaulus.com/jounal/mac/installing_python_osx/">Installing / Updating Python on OS X | Wolf Paulus</a></li>
<li><a href="https://gist.github.com/goldsmith/7163055">When I upgraded my Mac to OS X Mavericks, a lot of utilities (like Python, virtualenv, Xcode) broke, and it was pretty stressful trying to get it all set back up. Hopefully this guide can spare you some of that pain.Note: I'm by no means a Linux or Mac ex</a></li>
</ul>
</li>
</ul>
<p>Mavericks 对 Python 框架的调整,也的确有其原由的...</p>
<p>当然,好书要配合好代码,</p>
<p>及时 fork 一个自个儿可以折腾的: <a href="https://github.com/OpenBookProjects/pydata-book">OpenBookProjects/pydata-book</a></p>
<h2 id="changelog">Changelog<a class="headerlink" href="#changelog" title="Permanent link">¶</a></h2>
<ul>
<li>140603 完成环境探索,总结</li>
<li>140527 <a href="http://www.amazon.cn/gp/product/B00KD7Q7U2/ref=oh_d__o00_details_o00__i00?ie=UTF8&psc=1">"利用Python进行数据分析" Wes McKinney, 唐学韬 (Kindle电子书)</a></li>
</ul>rst2s5 小折腾2014-05-07T00:00:00+08:002014-05-07T16:57:32+08:00Zoom.Quiettag:blog.zoomquiet.io,2014-05-07:/rst2s5-upgraded.html
<h1 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h1>
<p><a href="http://blog.zoomquiet.org/pyblosxom/2010/09/index.html">rst2s5 ~ 好用的S5生成宏 @ 2010-09-18 23:23 - Zoom.Quiet's PyBlosxom blogging</a></p>
<p>所以 2011 以后所有发布的幻灯都是 rest2s5 生成的了:</p>
<p><a href="http://s5.zoomquiet.io/">s5.zoomquiet.io</a></p>
<h1 id="_2">问题<a class="headerlink" href="#_2" title="Permanent link">¶</a></h1>
<p>忽然发现生成的代码颜色很 …</p>
<h1 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h1>
<p><a href="http://blog.zoomquiet.org/pyblosxom/2010/09/index.html">rst2s5 ~ 好用的S5生成宏 @ 2010-09-18 23:23 - Zoom.Quiet's PyBlosxom blogging</a></p>
<p>所以 2011 以后所有发布的幻灯都是 rest2s5 生成的了:</p>
<p><a href="http://s5.zoomquiet.io/">s5.zoomquiet.io</a></p>
<h1 id="_2">问题<a class="headerlink" href="#_2" title="Permanent link">¶</a></h1>
<p>忽然发现生成的代码颜色很奇怪,在黑色背景中,很多元素几乎看不见</p>
<h1 id="_3">分析<a class="headerlink" href="#_3" title="Permanent link">¶</a></h1>
<p>4年前的生成脚本,和最新 pygments 接口不匹配了,,,</p>
<h1 id="_4">解决<a class="headerlink" href="#_4" title="Permanent link">¶</a></h1>
<p>参考:</p>
<ul>
<li><a href="http://pygments.org/docs/rstdirective/">Using Pygments in ReST documents — Pygments</a></li>
<li><a href="http://morgangoose.com/blog/2010/09/12/using-rst-for-presentations/">Using rst for presentations</a></li>
<li><a href="http://hackmap.blogspot.com/2009/10/rst2s5-with-syntax-highlighting.html">rst2s5 with syntax highlighting</a></li>
<li><a href="http://superuser.com/questions/374509/where-can-i-find-a-gallery-of-pygments-css-files">python - Where can I find a gallery of Pygments CSS files - Super User</a></li>
</ul>
<p>对比:</p>
<ul>
<li><a href="http://matt-good.net/files/software-dev-with-trac/rst2s5">rst2s5.py</a></li>
<li><a href="http://bpgeo.googlecode.com/svn/trunk/rst2s5_template/rst-directive.py">rst-directive.py</a></li>
</ul>
<p>发现就是样式的声明问题:
于是就追加了一个参数: <code>style="monokai"</code></p>
<div class="highlight"><pre><span></span><code><span class="c1"># ...</span>
<span class="n">formatter</span> <span class="o">=</span> <span class="n">get_formatter_by_name</span><span class="p">(</span><span class="s1">'html'</span>
<span class="p">,</span> <span class="n">noclasses</span><span class="o">=</span><span class="kc">True</span>
<span class="p">,</span> <span class="n">style</span><span class="o">=</span><span class="s2">"monokai"</span>
<span class="p">)</span>
</code></pre></div>
<p>搞掂!</p>
<p>另外,也随手变更了一下注册的 <code>directive</code> ~ 指令:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># Register the directive with docutils.</span>
<span class="c1">#rst.directives.register_directive('code-block', code_block)</span>
<span class="c1">#rst.roles.register_local_role('code-block', code_role)</span>
<span class="n">rst</span><span class="o">.</span><span class="n">directives</span><span class="o">.</span><span class="n">register_directive</span><span class="p">(</span><span class="s1">'sourcecode'</span><span class="p">,</span> <span class="n">code_block</span><span class="p">)</span>
<span class="n">rst</span><span class="o">.</span><span class="n">roles</span><span class="o">.</span><span class="n">register_local_role</span><span class="p">(</span><span class="s1">'sourcecode'</span><span class="p">,</span> <span class="n">code_role</span><span class="p">)</span>
</code></pre></div>
<p>这样俺在 Leo 中写:</p>
<p><img alt="140507-rst2s5-source.png" src="http://zoomq.qiniudn.com/ZQCollection/snap/140507-rst2s5-source.png"/></p>
<p>就可以一键生成为幻灯中的:</p>
<p><img alt="140507-rst2s5-slide.png" src="http://zoomq.qiniudn.com/ZQCollection/snap/140507-rst2s5-slide.png"/></p>ScrapBook 生存指南2014-02-26T00:00:00+08:002014-05-05T10:56:16+08:00Zoom.Quiettag:blog.zoomquiet.io,2014-02-26:/livin-scrapbook.html
<p><code>7.7G ZqFLOSS</code> 复制改进后,为毛多了?!</p>
<div class="highlight"><pre><span></span><code><span class="n">zoomq</span><span class="w"> </span><span class="err">@</span><span class="w"> </span><span class="n">MBP111216ZQ</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="o">~/</span><span class="n">KuaiPan</span><span class="o">/</span><span class="n">zScrapBook</span>
<span class="o">$</span><span class="w"> </span><span class="n">du</span><span class="w"> </span><span class="o">-</span><span class="n">hs</span><span class="w"> </span><span class="o">*</span>
<span class="mf">4.0</span><span class="n">K</span><span class="w"> </span><span class="mi">7</span><span class="n">niu</span><span class="o">-</span><span class="n">devrel</span><span class="o">.</span><span class="n">json</span>
<span class="mf">4.0</span><span class="n">K</span><span class="w"> </span><span class="mi">7</span><span class="n">niu</span><span class="o">-</span><span class="n">floss</span><span class="o">.</span><span class="n">json</span>
<span class="mf">4.0</span><span class="n">K</span><span class="w"> </span><span class="mi">7</span><span class="n">niu</span><span class="o">-</span><span class="n">skm</span><span class="o">.</span><span class="n">json</span>
<span class="mf">5.5</span><span class="n">G</span><span class="w"> </span><span class="n">ZqDevRel</span>
<span class="mf">6.4</span><span class="n">G</span><span class="w"> </span><span class="n">ZqFLOSS</span>
<span class="mf">3.5 …</span></code></pre></div>
<p><code>7.7G ZqFLOSS</code> 复制改进后,为毛多了?!</p>
<div class="highlight"><pre><span></span><code><span class="n">zoomq</span><span class="w"> </span><span class="err">@</span><span class="w"> </span><span class="n">MBP111216ZQ</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="o">~/</span><span class="n">KuaiPan</span><span class="o">/</span><span class="n">zScrapBook</span>
<span class="o">$</span><span class="w"> </span><span class="n">du</span><span class="w"> </span><span class="o">-</span><span class="n">hs</span><span class="w"> </span><span class="o">*</span>
<span class="mf">4.0</span><span class="n">K</span><span class="w"> </span><span class="mi">7</span><span class="n">niu</span><span class="o">-</span><span class="n">devrel</span><span class="o">.</span><span class="n">json</span>
<span class="mf">4.0</span><span class="n">K</span><span class="w"> </span><span class="mi">7</span><span class="n">niu</span><span class="o">-</span><span class="n">floss</span><span class="o">.</span><span class="n">json</span>
<span class="mf">4.0</span><span class="n">K</span><span class="w"> </span><span class="mi">7</span><span class="n">niu</span><span class="o">-</span><span class="n">skm</span><span class="o">.</span><span class="n">json</span>
<span class="mf">5.5</span><span class="n">G</span><span class="w"> </span><span class="n">ZqDevRel</span>
<span class="mf">6.4</span><span class="n">G</span><span class="w"> </span><span class="n">ZqFLOSS</span>
<span class="mf">3.5</span><span class="n">G</span><span class="w"> </span><span class="n">ZqSKM</span>
<span class="w"> </span><span class="mf">9.5</span><span class="n">M</span><span class="w"> </span><span class="n">scraotools_ZqDevRel</span><span class="o">.</span><span class="n">pkl</span>
<span class="w"> </span><span class="mi">14</span><span class="n">M</span><span class="w"> </span><span class="n">scraotools_ZqFLOSS</span><span class="o">.</span><span class="n">pkl</span>
<span class="mf">1.6</span><span class="n">M</span><span class="w"> </span><span class="n">scraotools_ZqSKM</span><span class="o">.</span><span class="n">pkl</span>
</code></pre></div>
<h2 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p>很久以前, 俺和大家一样,收集整理网络资源的习惯组织方式是:</p>
<ul>
<li>目录 (htm 抓网页)</li>
<li>刻光盘</li>
</ul>
<p>然后,发觉目录/内容超过两屏后基本什么也找不到了,
当然,后来使用了 google 的桌面搜索,
当然,那时还是 M$ 时代,</p>
<p>不过,在这个折腾的过程中,也明确了:</p>
<ul>
<li>资料的收集要配合自个儿的知识框架</li>
<li>搜索也必须知道搜索什么,而中文的岐义/复义/多义 太多,基本不可用作搜索关键词</li>
<li>pdf/word/ppt 之类的专用格式文档基本是废的,无法快速使用</li>
</ul>
<p>所以,后来上了 FireFox 后,用上了 ScrapBook 这一杀手级扩展,
资料的收集过程变成:</p>
<ol>
<li>浏览过程中,自然的挖掘,随手抓取到临时分类中</li>
<li>快速精读一遍,用内置高亮工具,标注重点</li>
<li>合理移动到对应的分类中</li>
<li>使用时,直接进入对应分类,或是用标题关键词搜索出来</li>
</ol>
<p>ScrapBook 是结合了本地目录管理+内置全文搜索的浏览器扩展工具.</p>
<p>一切安定了起来</p>
<h2 id="_2">发展<a class="headerlink" href="#_2" title="Permanent link">¶</a></h2>
<p>慢慢的,快速收集整理了上万个网页,才发现,好的网页内容:</p>
<ul>
<li>一般不长久,原始网站总是很快死亡</li>
<li>而相同的内容在多次转抄过程中总是有丢失</li>
<li>Google 的搜索镜像也不一定靠谱</li>
<li>大家通过书签记录的网页,基本上90天后就很难点击开了</li>
</ul>
<p>所以,就有了将个人收集分享出来的想法:</p>
<ul>
<li>ScrapBook 有导出目录树的功能</li>
<li>所以,一开始就是简单的进行导出</li>
<li>然后,用 rsync 同步到自个儿的官网空间</li>
</ul>
<p>但是,慢慢的,网络数量突破3万时,根索引的目录树就超过了10M!</p>
<ul>
<li>大家就反应首页很难打开了</li>
<li>这才知道真的有人在俺的分享网站中找东西!</li>
</ul>
<p>于是有了: <a href="https://github.com/ZoomQuiet/scrapbooktools/blob/master/expidxlevels.py">scrapbooktools/expidxlevels.py at master · ZoomQuiet/scrapbooktools</a></p>
<p>单纯的原样分享就变成了:</p>
<ul>
<li><a href="http://floss.zoomquiet.io/tree/">{ZqFLOSS} index tree exp. As HTML - ScrapBook</a></li>
<li><a href="http://skm.zoomquiet.io/tree/">{ZqSKM} index tree exp. As HTML - ScrapBook</a></li>
</ul>
<h2 id="_3">问题<a class="headerlink" href="#_3" title="Permanent link">¶</a></h2>
<p>但是,突然有一天,无法在常用的 ScrapBook 界面中对标题进行搜索了
能将整个浏览器都卡死...</p>
<p>再查, <code>ZqFLOSS</code> 目录已经突破5万页面,索引 xml 也超过了 25 M!</p>
<p>不得以再次分库,并分享:</p>
<ul>
<li><a href="http://devrel.zoomquiet.io/tree/">{ZqDevRel} index tree exp. As HTML - ScrapBook</a></li>
</ul>
<p>可是,奇怪的是分离了本地 ScrapBook 数据仓库后,问题依旧,
而且, <code>ZqFLOSS</code> 分离前有 <code>7.7G</code>;
可是拆分为两个仓库后,体积相互加,竟然几近 double !</p>
<p>于是怀疑多次手工批量删除时,造成了孤悬文件,然后就有了:</p>
<ul>
<li><a href="https://github.com/ZoomQuiet/scrapbooktools/blob/master/chkscrap.py">scrapbooktools/chkscrap.py at master · ZoomQuiet/scrapbooktools</a></li>
<li><a href="https://github.com/ZoomQuiet/scrapbooktools/blob/master/scrap_re_rdf.py">scrapbooktools/scrap_re_rdf.py at master · ZoomQuiet/scrapbooktools</a></li>
</ul>
<p>分别对数据目录,以及索引 xml 进行清查</p>
<p>但是,只有几个丢失...</p>
<h2 id="_4">分析<a class="headerlink" href="#_4" title="Permanent link">¶</a></h2>
<p>目测是 FireFox 升级,强行切换了JS 解析内核后,带来的少数不兼容,
导致了对一定体积的 XML 进行内存调度时,出了问题...</p>
<p>暂时无法解决.</p>
<p>已经向作者吼过,看RP 了...</p>
<h1 id="changelog">Changelog<a class="headerlink" href="#changelog" title="Permanent link">¶</a></h1>
<ul>
<li>140405 无解的快速总结</li>
<li>140217 开始回顾</li>
</ul>如何基于CB3构建家庭服务器2014-01-27T23:48:00+08:002014-05-05T11:58:26+08:00Zoom.Quiettag:blog.zoomquiet.io,2014-01-27:/cb3-howto-make-hmsrv.html
<p><a href="http://blog.zoomquiet.io/cbi-zq-install.html">CBInstallfest 的体验</a>
之后,总是要一步步完成心目中的 家服务器</p>
<h1 id="issue">Issue<a class="headerlink" href="#issue" title="Permanent link">¶</a></h1>
<p>基于CB3使用 lununtu-server-VGA 操作系统</p>
<ul>
<li>环境:</li>
<li>.bashrc</li>
<li>
<p>.inputrc</p>
</li>
<li>
<p>预装: </p>
</li>
<li>sshd</li>
<li>apt-fast<ul>
<li><a href="http://www.mattparnell.com/linux/apt-fast/">Index of /linux/apt-fast</a></li>
</ul>
</li>
<li>vim</li>
<li>mc</li>
<li>
<p>...</p>
</li>
<li>
<p>不要: </p>
</li>
<li>php</li>
<li>mysql</li>
<li>apache …</li></ul>
<p><a href="http://blog.zoomquiet.io/cbi-zq-install.html">CBInstallfest 的体验</a>
之后,总是要一步步完成心目中的 家服务器</p>
<h1 id="issue">Issue<a class="headerlink" href="#issue" title="Permanent link">¶</a></h1>
<p>基于CB3使用 lununtu-server-VGA 操作系统</p>
<ul>
<li>环境:</li>
<li>.bashrc</li>
<li>
<p>.inputrc</p>
</li>
<li>
<p>预装: </p>
</li>
<li>sshd</li>
<li>apt-fast<ul>
<li><a href="http://www.mattparnell.com/linux/apt-fast/">Index of /linux/apt-fast</a></li>
</ul>
</li>
<li>vim</li>
<li>mc</li>
<li>
<p>...</p>
</li>
<li>
<p>不要: </p>
</li>
<li>php</li>
<li>mysql</li>
<li>apache</li>
</ul>
<h1 id="todo">TODO<a class="headerlink" href="#todo" title="Permanent link">¶</a></h1>
<p>为了完全替代俺家原先的家庭服务器,可以支持多系统的内网络使用,
还要折腾的事儿有:</p>
<ol>
<li>通过 USB 挂接 FreeBSD 格式化的 UFS 分区</li>
<li>通过板载 SATA 接口,加装 2.5吋 1T 新硬盘</li>
<li>安装 Samba 系统,提供空间给其它 M$ 设备使用</li>
<li>安装 netatalk ,支持 <code>Apple Time Machine</code></li>
<li>安装 MLDonkey 通过网页控制 <code>P2P</code> 下载</li>
<li>安装 MiniDLNA 发布家庭媒体服务,支持远程播放下载的电影</li>
</ol>
<p>...</p>
<p>总之,要搾干 CB 的一切潜能!</p>
<h2 id="_1">分析<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p>之前类似的系统在 Ubuntu/FreeBSD 上都折腾过,应该没有什么问题的...</p>
<p>所以,出了各种问题,用了半个月才断断续续的折腾完!</p>
<p>背景:</p>
<ul>
<li>原先家庭服务器是一台兼容PC, FreeBSD8.2, 4G内存,1T硬盘+30G启动盘, 已经死亡</li>
<li>目标环境是:</li>
<li>CB3</li>
<li>2G 内存</li>
<li>2G 启动盘</li>
<li>1T 近线2吋盘</li>
<li>1T U盘,3吋老盘,恢复数据</li>
</ul>
<h1 id="_2">过程<a class="headerlink" href="#_2" title="Permanent link">¶</a></h1>
<p>宏观回顾一下要点:</p>
<ol>
<li>nand 的系统要选择正确,否则 VGA 是支持不能的</li>
<li>不作死不会死,千万别折腾不必要的功能/配置</li>
<li>外挂硬盘以及历史数据,如果当初没有想到有迁移的这天只能辛苦人肉搬</li>
<li>yum 越来越靠谱了,但是,还是相信 apt 为好</li>
</ol>
<h2 id="cb">CB 初始化<a class="headerlink" href="#cb" title="Permanent link">¶</a></h2>
<p>参考: <a href="http://blog.zoomquiet.io/cbi-zq-install.html">CBInstallfest 的体验</a>
之后,总是要一步步完成心目中的 家服务器</p>
<h2 id="_3">系统整顿<a class="headerlink" href="#_3" title="Permanent link">¶</a></h2>
<p>CB 自制的 lubuntu 系统,最扯的事儿是:</p>
<div class="highlight"><pre><span></span><code>居然
没有
默认
安装
SSH
</code></pre></div>
<p>真心让俺折腾了很久才发现这么奇葩的设计...</p>
<p>然后进行一系列习惯环境的配置, 特别是:</p>
<ul>
<li>第一时间快速 axel 以及 <a href="http://wiki.ubuntu.org.cn/Apt-fast">Apt-fast</a></li>
<li>
<p>习惯的各种 shell 别名:</p>
<p>:::bash
alias ses='sudo gedit /etc/apt/sources.list'
alias acs='apt-cache search'
alias agu='sudo apt-fast update'
alias agg='sudo apt-fast upgrade'
alias agi='sudo apt-fast install'
alias agclean='sudo apt-get clean && sudo apt-get autoclean'
alias apse='aptitude search'
alias apsh='sudo aptitude show'
alias apu='sudo aptitude update'
alias apg='sudo aptitude safe-upgrade'
alias api='sudo apt-get install'
alias aprm='sudo aptitude remove'
alias apclean='sudo aptitude autoclean'
alias ppaddkey='sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys'</p>
</li>
</ul>
<p>然后,第一时间杀灭预安装的 Apache,MySQL,PHP</p>
<p>参考:</p>
<ul>
<li>
<p><a href="http://my.oschina.net/sherwayne/blog/108685">Ubuntu卸载Apache+Mysql+PHP - 徐航的个人页面 - 开源中国社区</a></p>
<p>:::bash
$ sudo apt-get --purge remove apache2
$ sudo apt-get --purge remove apache2.2-common
$ sudo apt-get autoremove apache2
$ sudo aptitude purge mysql-server mysql-server-5.0
$ sudo apt-get autoremove php5
$ sudo rm -rf /var/lib/mysql</p>
</li>
</ul>
<h3 id="utf8">UTF8<a class="headerlink" href="#utf8" title="Permanent link">¶</a></h3>
<p>默认的: </p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>locale
<span class="nv">LANG</span><span class="o">=</span>
<span class="nv">LANGUAGE</span><span class="o">=</span>
<span class="nv">LC_CTYPE</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_NUMERIC</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_TIME</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_COLLATE</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_MONETARY</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_MESSAGES</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_PAPER</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_NAME</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_ADDRESS</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_TELEPHONE</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_MEASUREMENT</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_IDENTIFICATION</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_ALL</span><span class="o">=</span>
</code></pre></div>
<p>参考:</p>
<ul>
<li><a href="http://fruit.je/utf-8">Using UTF-8 in Debian</a></li>
<li><a href="http://wiki.ubuntu.org.cn/%E4%BF%AE%E6%94%B9locale">修改locale - Ubuntu中文</a></li>
</ul>
<p>重启后依然!</p>
<div class="highlight"><pre><span></span><code>zoomq@cubietruck:~$<span class="w"> </span>locale
<span class="nv">LANG</span><span class="o">=</span>
<span class="nv">LANGUAGE</span><span class="o">=</span>
<span class="nv">LC_CTYPE</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_NUMERIC</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_TIME</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_COLLATE</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_MONETARY</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_MESSAGES</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_PAPER</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_NAME</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_ADDRESS</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_TELEPHONE</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_MEASUREMENT</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_IDENTIFICATION</span><span class="o">=</span><span class="s2">"POSIX"</span>
<span class="nv">LC_ALL</span><span class="o">=</span>
</code></pre></div>
<p>但是,从 screen 中进入时,就已经</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>locale
<span class="nv">LANG</span><span class="o">=</span>en_US.UTF-8
<span class="nv">LANGUAGE</span><span class="o">=</span>en_US:en
<span class="nv">LC_CTYPE</span><span class="o">=</span><span class="s2">"en_US.UTF-8"</span>
<span class="nv">LC_NUMERIC</span><span class="o">=</span><span class="s2">"en_US.UTF-8"</span>
<span class="nv">LC_TIME</span><span class="o">=</span><span class="s2">"en_US.UTF-8"</span>
<span class="nv">LC_COLLATE</span><span class="o">=</span><span class="s2">"en_US.UTF-8"</span>
<span class="nv">LC_MONETARY</span><span class="o">=</span><span class="s2">"en_US.UTF-8"</span>
<span class="nv">LC_MESSAGES</span><span class="o">=</span><span class="s2">"en_US.UTF-8"</span>
<span class="nv">LC_PAPER</span><span class="o">=</span><span class="s2">"en_US.UTF-8"</span>
<span class="nv">LC_NAME</span><span class="o">=</span><span class="s2">"en_US.UTF-8"</span>
<span class="nv">LC_ADDRESS</span><span class="o">=</span><span class="s2">"en_US.UTF-8"</span>
<span class="nv">LC_TELEPHONE</span><span class="o">=</span><span class="s2">"en_US.UTF-8"</span>
<span class="nv">LC_MEASUREMENT</span><span class="o">=</span><span class="s2">"en_US.UTF-8"</span>
<span class="nv">LC_IDENTIFICATION</span><span class="o">=</span><span class="s2">"en_US.UTF-8"</span>
<span class="nv">LC_ALL</span><span class="o">=</span>
</code></pre></div>
<p>好吧,也算解决,
目测是因为系统默许不加载用户配置,
但是,一般俺只在 Screen 光辉中生存的,所以,不是问题.</p>
<h2 id="_4">数据迁移<a class="headerlink" href="#_4" title="Permanent link">¶</a></h2>
<p>专门问过高人:</p>
<div class="highlight"><pre><span></span><code><span class="n">from</span><span class="o">:</span><span class="w"> </span><span class="n">Zoom</span><span class="o">.</span><span class="na">Quiet</span><span class="w"> </span><span class="o"><</span><span class="n">zoom</span><span class="o">.</span><span class="na">quiet</span><span class="err">@</span><span class="n">gmail</span><span class="o">.</span><span class="na">com</span><span class="o">></span>
<span class="n">to</span><span class="o">:</span><span class="w"> </span><span class="n">shlug</span><span class="w"> </span><span class="o"><</span><span class="n">shlug</span><span class="err">@</span><span class="n">googlegroups</span><span class="o">.</span><span class="na">com</span><span class="o">></span>
<span class="n">date</span><span class="o">:</span><span class="w"> </span><span class="n">Mon</span><span class="o">,</span><span class="w"> </span><span class="n">Jan</span><span class="w"> </span><span class="mi">20</span><span class="o">,</span><span class="w"> </span><span class="mi">2014</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="mi">4</span><span class="o">:</span><span class="mi">35</span><span class="w"> </span><span class="n">PM</span>
<span class="n">subject</span><span class="o">:</span><span class="w"> </span><span class="mi">1</span><span class="n">Tb</span><span class="w"> </span><span class="err">的</span><span class="mf">2.5</span><span class="err">吋盘给</span><span class="w"> </span><span class="n">Ubuntu</span><span class="w"> </span><span class="err">用应该选择什么</span><span class="n">FS</span><span class="o">?</span>
</code></pre></div>
<p>参考: <a href="http://floss.zoomquiet.io/data/20110828225725/index.html">linux下的文件系统选型 | shell's home</a>
以及相关的各种文档,</p>
<p>进行了各种尝试,只能说那真是千辛万苦哪:</p>
<ul>
<li>老硬盘不格式化</li>
<li>lununtu 直接/USB加挂3吋盘<ul>
<li>无法对 UFS 进行读写</li>
<li>无解</li>
</ul>
</li>
<li>老硬盘格式化</li>
<li>购买了2吋 1T盘, etx4 格式化,挂好</li>
<li>怎么将老盘的 BSD 文件系统中的数据迁移出来?<ul>
<li>MAC 挂 UFS ~ 无解</li>
<li>Linux 挂 UFS ~ 失败</li>
<li>FreeBSD 挂 UFS </li>
<li>嚓了! 也失败!</li>
<li>这不科学,再换一台BSD ,一下子就成功了!</li>
<li>原来是 BSD 8.2 和 9.1 的系统不同导致...</li>
</ul>
</li>
<li>然后,就变成:<ul>
<li>MAC 接 1T 的专用U盘(原先用作 TimeMachine 空间的)</li>
<li>再用 sshfs 远程挂上机房的 BSD 主机</li>
<li>人工识别可用数据,逐一复制</li>
</ul>
</li>
<li>恢复上线</li>
<li>所有数据在 MAC 专用U盘中了</li>
<li>回家将老盘用外置U盘接上</li>
<li>从 lununtu 中重新分区,格式化为 <code>vfat</code> <ul>
<li><code>这是唯一一个所有系统都良好兼容的文件格式,工具又多</code> ~ shell909090 曰过</li>
</ul>
</li>
<li>然后,同样的通过网络 用 sshfs 挂上 CB 中的所有硬盘</li>
<li>人工从 MAC 中灌回...</li>
</ul>
<p>整个 700多G 数据,就这样迁移到了 CB 控制的两个硬盘共 2T 空间中...</p>
<h3 id="_5">相关片段<a class="headerlink" href="#_5" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>cat<span class="w"> </span>/proc/partitions
major<span class="w"> </span>minor<span class="w"> </span><span class="c1">#blocks name</span>
<span class="w"> </span><span class="m">93</span><span class="w"> </span><span class="m">0</span><span class="w"> </span><span class="m">7520256</span><span class="w"> </span>nand
<span class="w"> </span><span class="m">93</span><span class="w"> </span><span class="m">1</span><span class="w"> </span><span class="m">65536</span><span class="w"> </span>nanda
<span class="w"> </span><span class="m">93</span><span class="w"> </span><span class="m">2</span><span class="w"> </span><span class="m">2097152</span><span class="w"> </span>nandb
<span class="w"> </span><span class="m">93</span><span class="w"> </span><span class="m">3</span><span class="w"> </span><span class="m">5341184</span><span class="w"> </span>nandc
<span class="w"> </span><span class="m">8</span><span class="w"> </span><span class="m">0</span><span class="w"> </span><span class="m">976762584</span><span class="w"> </span>sda
<span class="w"> </span><span class="m">8</span><span class="w"> </span><span class="m">16</span><span class="w"> </span><span class="m">1953514584</span><span class="w"> </span>sdb
<span class="w"> </span><span class="m">8</span><span class="w"> </span><span class="m">17</span><span class="w"> </span><span class="m">204800</span><span class="w"> </span>sdb1
<span class="w"> </span><span class="m">8</span><span class="w"> </span><span class="m">18</span><span class="w"> </span><span class="m">781380608</span><span class="w"> </span>sdb2
<span class="w"> </span><span class="m">8</span><span class="w"> </span><span class="m">19</span><span class="w"> </span><span class="m">1171928064</span><span class="w"> </span>sdb3
$<span class="w"> </span>sudo<span class="w"> </span>mount.exfat-fuse<span class="w"> </span>/dev/sdb2<span class="w"> </span>/mnt/bk2wk
$<span class="w"> </span>sudo<span class="w"> </span>mount.exfat-fuse<span class="w"> </span>/dev/sdb3<span class="w"> </span>/mnt/dl4p2p
</code></pre></div>
<p>但是, 远程 sshfs 后目录只读!?</p>
<ul>
<li>只能用 root 的远程用户登录...</li>
<li>最好用 密匙...</li>
<li><a href="https://help.ubuntu.com/community/SSH/OpenSSH/Keys">SSH/OpenSSH/Keys - Community Ubuntu Documentation</a></li>
</ul>
<h3 id="_6">外置硬盘盒<a class="headerlink" href="#_6" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code><span class="err">$</span><span class="w"> </span><span class="n">dmesg</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">grep</span><span class="w"> </span><span class="n">da0</span>
<span class="n">ada0</span><span class="w"> </span><span class="k">at</span><span class="w"> </span><span class="n">ata4</span><span class="w"> </span><span class="n">bus</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="n">scbus2</span><span class="w"> </span><span class="n">target</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="n">lun</span><span class="w"> </span><span class="mi">0</span>
<span class="nl">ada0</span><span class="p">:</span><span class="w"> </span><span class="o"><</span><span class="n">ST3160815AS</span><span class="w"> </span><span class="mf">3.</span><span class="k">ADA</span><span class="o">></span><span class="w"> </span><span class="n">ATA</span><span class="o">-</span><span class="mi">7</span><span class="w"> </span><span class="n">SATA</span><span class="w"> </span><span class="mf">2.</span><span class="n">x</span><span class="w"> </span><span class="n">device</span>
<span class="nl">ada0</span><span class="p">:</span><span class="w"> </span><span class="mf">300.000</span><span class="n">MB</span><span class="o">/</span><span class="n">s</span><span class="w"> </span><span class="n">transfers</span><span class="w"> </span><span class="p">(</span><span class="n">SATA</span><span class="w"> </span><span class="mf">2.</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">UDMA5</span><span class="p">,</span><span class="w"> </span><span class="n">PIO</span><span class="w"> </span><span class="mi">8192</span><span class="n">bytes</span><span class="p">)</span>
<span class="nl">ada0</span><span class="p">:</span><span class="w"> </span><span class="mi">152587</span><span class="n">MB</span><span class="w"> </span><span class="p">(</span><span class="mi">312500000</span><span class="w"> </span><span class="mi">512</span><span class="w"> </span><span class="n">byte</span><span class="w"> </span><span class="nl">sectors</span><span class="p">:</span><span class="w"> </span><span class="mi">16</span><span class="n">H</span><span class="w"> </span><span class="mi">63</span><span class="n">S</span><span class="o">/</span><span class="n">T</span><span class="w"> </span><span class="mi">16383</span><span class="n">C</span><span class="p">)</span>
<span class="nl">ada0</span><span class="p">:</span><span class="w"> </span><span class="n">Previously</span><span class="w"> </span><span class="n">was</span><span class="w"> </span><span class="n">known</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">ad8</span>
<span class="n">Trying</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="n">mount</span><span class="w"> </span><span class="n">root</span><span class="w"> </span><span class="k">from</span><span class="w"> </span><span class="nl">ufs</span><span class="p">:</span><span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">ada0s1a</span><span class="w"> </span><span class="o">[</span><span class="n">rw</span><span class="o">]</span><span class="p">...</span>
<span class="n">da0</span><span class="w"> </span><span class="k">at</span><span class="w"> </span><span class="n">umass</span><span class="o">-</span><span class="n">sim0</span><span class="w"> </span><span class="n">bus</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="n">scbus6</span><span class="w"> </span><span class="n">target</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="n">lun</span><span class="w"> </span><span class="mi">0</span>
<span class="nl">da0</span><span class="p">:</span><span class="w"> </span><span class="o"><</span><span class="n">ATA</span><span class="w"> </span><span class="n">ST2000DL003</span><span class="o">-</span><span class="mi">9</span><span class="n">VT1</span><span class="w"> </span><span class="n">CC3C</span><span class="o">></span><span class="w"> </span><span class="n">Fixed</span><span class="w"> </span><span class="n">Direct</span><span class="w"> </span><span class="n">Access</span><span class="w"> </span><span class="n">SCSI</span><span class="o">-</span><span class="mi">6</span><span class="w"> </span><span class="n">device</span>
<span class="nl">da0</span><span class="p">:</span><span class="w"> </span><span class="mf">40.000</span><span class="n">MB</span><span class="o">/</span><span class="n">s</span><span class="w"> </span><span class="n">transfers</span>
<span class="nl">da0</span><span class="p">:</span><span class="w"> </span><span class="mi">1907729</span><span class="n">MB</span><span class="w"> </span><span class="p">(</span><span class="mi">3907029168</span><span class="w"> </span><span class="mi">512</span><span class="w"> </span><span class="n">byte</span><span class="w"> </span><span class="nl">sectors</span><span class="p">:</span><span class="w"> </span><span class="mi">255</span><span class="n">H</span><span class="w"> </span><span class="mi">63</span><span class="n">S</span><span class="o">/</span><span class="n">T</span><span class="w"> </span><span class="mi">243201</span><span class="n">C</span><span class="p">)</span>
<span class="err">$</span><span class="w"> </span><span class="n">gpart</span><span class="w"> </span><span class="n">show</span><span class="w"> </span><span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">da0</span>
<span class="o">=></span><span class="w"> </span><span class="mi">34</span><span class="w"> </span><span class="mi">3907029101</span><span class="w"> </span><span class="n">da0</span><span class="w"> </span><span class="n">GPT</span><span class="w"> </span><span class="p">(</span><span class="mf">1.8</span><span class="n">T</span><span class="p">)</span>
<span class="w"> </span><span class="mi">34</span><span class="w"> </span><span class="mi">6</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="k">free</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="p">(</span><span class="mf">3.0</span><span class="n">k</span><span class="p">)</span>
<span class="w"> </span><span class="mi">40</span><span class="w"> </span><span class="mi">128</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">freebsd</span><span class="o">-</span><span class="n">boot</span><span class="w"> </span><span class="p">(</span><span class="mi">64</span><span class="n">k</span><span class="p">)</span>
<span class="w"> </span><span class="mi">168</span><span class="w"> </span><span class="mi">16777216</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="n">freebsd</span><span class="o">-</span><span class="n">ufs</span><span class="w"> </span><span class="p">(</span><span class="mf">8.0</span><span class="n">G</span><span class="p">)</span>
<span class="w"> </span><span class="mi">16777384</span><span class="w"> </span><span class="mi">3886022656</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="n">freebsd</span><span class="o">-</span><span class="n">ufs</span><span class="w"> </span><span class="p">(</span><span class="mf">1.8</span><span class="n">T</span><span class="p">)</span>
<span class="w"> </span><span class="mi">3902800040</span><span class="w"> </span><span class="mi">4229094</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="n">freebsd</span><span class="o">-</span><span class="n">swap</span><span class="w"> </span><span class="p">(</span><span class="mf">2.0</span><span class="n">G</span><span class="p">)</span>
<span class="w"> </span><span class="mi">3907029134</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="k">free</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="p">(</span><span class="mi">512</span><span class="n">B</span><span class="p">)</span>
</code></pre></div>
<h3 id="sshfs">伟光大的 sshfs<a class="headerlink" href="#sshfs" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code><span class="o">$</span><span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">link</span><span class="w"> </span><span class="n">fuse4x</span>
<span class="n">Linking</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">fuse4x</span><span class="o">/</span><span class="mf">0.9</span><span class="o">.</span><span class="mf">2.</span><span class="o">..</span><span class="w"> </span><span class="n">Warning</span><span class="p">:</span><span class="w"> </span><span class="n">Could</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="n">link</span><span class="w"> </span><span class="n">fuse4x</span><span class="o">.</span><span class="w"> </span><span class="n">Unlinking</span><span class="o">...</span>
<span class="n">Error</span><span class="p">:</span><span class="w"> </span><span class="n">Could</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="n">symlink</span><span class="w"> </span><span class="n">file</span><span class="p">:</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">fuse4x</span><span class="o">/</span><span class="mf">0.9</span><span class="o">.</span><span class="mi">2</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">pkgconfig</span><span class="o">/</span><span class="n">fuse</span><span class="o">.</span><span class="n">pc</span>
<span class="n">Target</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">pkgconfig</span><span class="o">/</span><span class="n">fuse</span><span class="o">.</span><span class="n">pc</span><span class="w"> </span><span class="n">already</span><span class="w"> </span><span class="n">exists</span><span class="o">.</span><span class="w"> </span><span class="n">You</span><span class="w"> </span><span class="n">may</span><span class="w"> </span><span class="n">need</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">delete</span><span class="w"> </span><span class="n">it</span><span class="o">.</span>
<span class="n">To</span><span class="w"> </span><span class="n">force</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">link</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">overwrite</span><span class="w"> </span><span class="n">all</span><span class="w"> </span><span class="n">other</span><span class="w"> </span><span class="n">conflicting</span><span class="w"> </span><span class="n">files</span><span class="p">,</span><span class="w"> </span><span class="n">do</span><span class="p">:</span>
<span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">link</span><span class="w"> </span><span class="o">--</span><span class="n">overwrite</span><span class="w"> </span><span class="n">formula_name</span>
<span class="n">To</span><span class="w"> </span><span class="n">list</span><span class="w"> </span><span class="n">all</span><span class="w"> </span><span class="n">files</span><span class="w"> </span><span class="n">that</span><span class="w"> </span><span class="n">would</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">deleted</span><span class="p">:</span>
<span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">link</span><span class="w"> </span><span class="o">--</span><span class="n">overwrite</span><span class="w"> </span><span class="o">--</span><span class="n">dry</span><span class="o">-</span><span class="n">run</span><span class="w"> </span><span class="n">formula_name</span>
<span class="n">zoomq</span><span class="w"> </span><span class="err">@</span><span class="w"> </span><span class="n">MBP111216ZQ</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">lib</span>
<span class="o">$</span><span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">link</span><span class="w"> </span><span class="o">--</span><span class="n">overwrite</span><span class="w"> </span><span class="n">fuse4x</span>
<span class="n">Linking</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">fuse4x</span><span class="o">/</span><span class="mf">0.9</span><span class="o">.</span><span class="mf">2.</span><span class="o">..</span><span class="w"> </span><span class="mi">7</span><span class="w"> </span><span class="n">symlinks</span><span class="w"> </span><span class="n">created</span>
<span class="o">$</span><span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">osxfuse</span>
<span class="o">==></span><span class="w"> </span><span class="n">Downloading</span><span class="w"> </span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">downloads</span><span class="o">.</span><span class="n">sf</span><span class="o">.</span><span class="n">net</span><span class="o">/</span><span class="n">project</span><span class="o">/</span><span class="n">machomebrew</span><span class="o">/</span><span class="n">Bottles</span><span class="o">/</span><span class="n">osxfuse</span><span class="o">-</span><span class="mf">2.6</span><span class="o">.</span><span class="mf">2.</span><span class="n">mavericks</span><span class="o">.</span><span class="n">bottle</span><span class="o">.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
<span class="o">==></span><span class="w"> </span><span class="n">Pouring</span><span class="w"> </span><span class="n">osxfuse</span><span class="o">-</span><span class="mf">2.6</span><span class="o">.</span><span class="mf">2.</span><span class="n">mavericks</span><span class="o">.</span><span class="n">bottle</span><span class="o">.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
<span class="o">==></span><span class="w"> </span><span class="n">Caveats</span>
<span class="n">If</span><span class="w"> </span><span class="n">upgrading</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">previous</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">osxfuse</span><span class="p">,</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">previous</span><span class="w"> </span><span class="n">kernel</span><span class="w"> </span><span class="n">extension</span>
<span class="n">will</span><span class="w"> </span><span class="n">need</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">unloaded</span><span class="w"> </span><span class="n">before</span><span class="w"> </span><span class="n">installing</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">new</span><span class="w"> </span><span class="n">version</span><span class="o">.</span><span class="w"> </span><span class="n">First</span><span class="p">,</span><span class="w"> </span><span class="n">check</span><span class="w"> </span><span class="n">that</span>
<span class="n">no</span><span class="w"> </span><span class="n">FUSE</span><span class="o">-</span><span class="n">based</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">systems</span><span class="w"> </span><span class="n">are</span><span class="w"> </span><span class="n">running</span><span class="p">:</span>
<span class="w"> </span><span class="n">mount</span><span class="w"> </span><span class="o">-</span><span class="n">t</span><span class="w"> </span><span class="n">osxfusefs</span>
<span class="n">Unmount</span><span class="w"> </span><span class="n">all</span><span class="w"> </span><span class="n">FUSE</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">systems</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">then</span><span class="w"> </span><span class="n">unload</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">kernel</span><span class="w"> </span><span class="n">extension</span><span class="p">:</span>
<span class="w"> </span><span class="n">sudo</span><span class="w"> </span><span class="n">kextunload</span><span class="w"> </span><span class="o">-</span><span class="n">b</span><span class="w"> </span><span class="n">com</span><span class="o">.</span><span class="n">github</span><span class="o">.</span><span class="n">osxfuse</span><span class="o">.</span><span class="n">filesystems</span><span class="o">.</span><span class="n">osxfusefs</span>
<span class="n">The</span><span class="w"> </span><span class="n">new</span><span class="w"> </span><span class="n">osxfuse</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">system</span><span class="w"> </span><span class="n">bundle</span><span class="w"> </span><span class="n">needs</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">installed</span><span class="w"> </span><span class="n">by</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">root</span><span class="w"> </span><span class="n">user</span><span class="p">:</span>
<span class="w"> </span><span class="n">sudo</span><span class="w"> </span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">cp</span><span class="w"> </span><span class="o">-</span><span class="n">RfX</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">osxfuse</span><span class="o">/</span><span class="mf">2.6</span><span class="o">.</span><span class="mi">2</span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Filesystems</span><span class="o">/</span><span class="n">osxfusefs</span><span class="o">.</span><span class="n">fs</span><span class="w"> </span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Filesystems</span>
<span class="w"> </span><span class="n">sudo</span><span class="w"> </span><span class="n">chmod</span><span class="w"> </span><span class="o">+</span><span class="n">s</span><span class="w"> </span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Filesystems</span><span class="o">/</span><span class="n">osxfusefs</span><span class="o">.</span><span class="n">fs</span><span class="o">/</span><span class="n">Support</span><span class="o">/</span><span class="n">load_osxfusefs</span>
<span class="o">==></span><span class="w"> </span><span class="n">Summary</span>
<span class="err">🍺</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">osxfuse</span><span class="o">/</span><span class="mf">2.6</span><span class="o">.</span><span class="mi">2</span><span class="p">:</span><span class="w"> </span><span class="mi">84</span><span class="w"> </span><span class="n">files</span><span class="p">,</span><span class="w"> </span><span class="mf">5.0</span><span class="n">M</span>
</code></pre></div>
<h3 id="exfat">exFAT<a class="headerlink" href="#exfat" title="Permanent link">¶</a></h3>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>cat<span class="w"> </span>/etc/lsb-release.bk
<span class="nv">DISTRIB_ID</span><span class="o">=</span>Linaro
<span class="nv">DISTRIB_RELEASE</span><span class="o">=</span><span class="m">13</span>.08
<span class="nv">DISTRIB_CODENAME</span><span class="o">=</span>raring
<span class="nv">DISTRIB_DESCRIPTION</span><span class="o">=</span><span class="s2">"Linaro 13.08"</span>
$<span class="w"> </span>sudo<span class="w"> </span>vi<span class="w"> </span>/etc/lsb-release
<span class="nv">DISTRIB_ID</span><span class="o">=</span>Ubuntu
<span class="nv">DISTRIB_RELEASE</span><span class="o">=</span><span class="m">13</span>.04
<span class="nv">DISTRIB_CODENAME</span><span class="o">=</span>raring
<span class="nv">DISTRIB_DESCRIPTION</span><span class="o">=</span><span class="s2">"Ubuntu 13.04"</span>
$<span class="w"> </span>sudo<span class="w"> </span>apt-add-repository<span class="w"> </span>ppa:relan/exfat
你将向系统添加如下<span class="w"> </span>PPA:
<span class="w"> </span>PPA<span class="w"> </span><span class="k">for</span><span class="w"> </span>the<span class="w"> </span>free<span class="w"> </span>exFAT<span class="w"> </span>file<span class="w"> </span>system<span class="w"> </span>implementation<span class="w"> </span>project:<span class="w"> </span>http://code.google.com/p/exfat/
<span class="w"> </span>更多信息:<span class="w"> </span>https://launchpad.net/~relan/+archive/exfat
按回车继续或者<span class="w"> </span>Ctrl+c<span class="w"> </span>取消添加
gpg:<span class="w"> </span>钥匙环‘/tmp/tmppjaczn/secring.gpg’已建立
gpg:<span class="w"> </span>钥匙环‘/tmp/tmppjaczn/pubring.gpg’已建立
gpg:<span class="w"> </span>下载密钥‘A252A784’,从<span class="w"> </span>hkp<span class="w"> </span>服务器<span class="w"> </span>keyserver.ubuntu.com
gpg:<span class="w"> </span>/tmp/tmppjaczn/trustdb.gpg:建立了信任度数据库
gpg:<span class="w"> </span>密钥<span class="w"> </span>A252A784:公钥“Launchpad<span class="w"> </span>Free<span class="w"> </span>exFAT<span class="w"> </span>file<span class="w"> </span>system<span class="w"> </span>implementation”已导入
gpg:<span class="w"> </span>合计被处理的数量:1
gpg:<span class="w"> </span>已导入:1<span class="w"> </span><span class="o">(</span>RSA:<span class="w"> </span><span class="m">1</span><span class="o">)</span>
OK
$<span class="w"> </span>acs<span class="w"> </span>exfat
exfat-fuse<span class="w"> </span>-<span class="w"> </span><span class="nb">read</span><span class="w"> </span>and<span class="w"> </span>write<span class="w"> </span>exFAT<span class="w"> </span>driver<span class="w"> </span><span class="k">for</span><span class="w"> </span>FUSE
exfat-utils<span class="w"> </span>-<span class="w"> </span>utilities<span class="w"> </span>to<span class="w"> </span>create,<span class="w"> </span>check,<span class="w"> </span>label<span class="w"> </span>and<span class="w"> </span>dump<span class="w"> </span>exFAT<span class="w"> </span>filesystem
$<span class="w"> </span>agi<span class="w"> </span>exfat-fuse
<span class="w"> </span>Working...<span class="w"> </span>this<span class="w"> </span>may<span class="w"> </span>take<span class="w"> </span>a<span class="w"> </span><span class="k">while</span>.
<span class="c1"># apt-fast mirror list: Mon Jan 27 16:42:10 UTC 2014</span>
http://ports.ubuntu.com/ubuntu-ports/pool/universe/f/fuse-exfat/exfat-fuse_1.0.1-1_armhf.deb
<span class="w"> </span><span class="nv">checksum</span><span class="o">=</span><span class="nv">md5</span><span class="o">=</span>fcacfbade2df1f97d72ba9912961883f
<span class="w"> </span><span class="nv">out</span><span class="o">=</span>exfat-fuse_1.0.1-1_armhf.deb
http://ports.ubuntu.com/ubuntu-ports/pool/universe/e/exfat-utils/exfat-utils_1.0.1-1_armhf.deb
<span class="w"> </span><span class="nv">checksum</span><span class="o">=</span><span class="nv">md5</span><span class="o">=</span>ef8bc2e59569645b7140e930e81809f3
<span class="w"> </span><span class="nv">out</span><span class="o">=</span>exfat-utils_1.0.1-1_armhf.deb
...
下载结果:
gid<span class="w"> </span><span class="p">|</span>stat<span class="p">|</span>avg<span class="w"> </span>speed<span class="w"> </span><span class="p">|</span>path/URI
<span class="o">======</span>+<span class="o">====</span>+<span class="o">===========</span>+<span class="o">=======================================================</span>
07028f<span class="p">|</span>OK<span class="w"> </span><span class="p">|</span><span class="w"> </span>66KiB/s<span class="p">|</span>/var/cache/apt/archives/apt-fast/exfat-fuse_1.0.1-1_armhf.deb
e4fa30<span class="p">|</span>OK<span class="w"> </span><span class="p">|</span><span class="w"> </span>40KiB/s<span class="p">|</span>/var/cache/apt/archives/apt-fast/exfat-utils_1.0.1-1_armhf.deb
状态标识:
<span class="o">(</span>OK<span class="o">)</span>:完成下载。
正在读取软件包列表...<span class="w"> </span>完成
正在分析软件包的依赖关系树
正在读取状态信息...<span class="w"> </span>完成
将会安装下列额外的软件包:
<span class="w"> </span>exfat-utils
下列【新】软件包将被安装:
<span class="w"> </span>exfat-fuse<span class="w"> </span>exfat-utils
升级了<span class="w"> </span><span class="m">0</span><span class="w"> </span>个软件包,新安装了<span class="w"> </span><span class="m">2</span><span class="w"> </span>个软件包,要卸载<span class="w"> </span><span class="m">0</span><span class="w"> </span>个软件包,有<span class="w"> </span><span class="m">1</span><span class="w"> </span>个软件包未被升级。
需要下载<span class="w"> </span><span class="m">0</span><span class="w"> </span>B/80.7<span class="w"> </span>kB<span class="w"> </span>的软件包。
解压缩后会消耗掉<span class="w"> </span><span class="m">248</span><span class="w"> </span>kB<span class="w"> </span>的额外空间。
您希望继续执行吗?<span class="o">[</span>Y/n<span class="o">]</span>
【警告】:下列软件包不能通过验证!
<span class="w"> </span>exfat-fuse<span class="w"> </span>exfat-utils
忽略了认证警告。
Selecting<span class="w"> </span>previously<span class="w"> </span>unselected<span class="w"> </span>package<span class="w"> </span>exfat-fuse.
<span class="o">(</span>正在读取数据库<span class="w"> </span>...<span class="w"> </span>系统当前共安装有<span class="w"> </span><span class="m">27896</span><span class="w"> </span>个文件和目录。<span class="o">)</span>
正在解压缩<span class="w"> </span>exfat-fuse<span class="w"> </span><span class="o">(</span>从<span class="w"> </span>.../exfat-fuse_1.0.1-1_armhf.deb<span class="o">)</span><span class="w"> </span>...
Selecting<span class="w"> </span>previously<span class="w"> </span>unselected<span class="w"> </span>package<span class="w"> </span>exfat-utils.
正在解压缩<span class="w"> </span>exfat-utils<span class="w"> </span><span class="o">(</span>从<span class="w"> </span>.../exfat-utils_1.0.1-1_armhf.deb<span class="o">)</span><span class="w"> </span>...
正在处理用于<span class="w"> </span>man-db<span class="w"> </span>的触发器...
正在设置<span class="w"> </span>exfat-fuse<span class="w"> </span><span class="o">(</span><span class="m">1</span>.0.1-1<span class="o">)</span><span class="w"> </span>...
正在设置<span class="w"> </span>exfat-utils<span class="w"> </span><span class="o">(</span><span class="m">1</span>.0.1-1<span class="o">)</span><span class="w"> </span>...
$<span class="w"> </span>sudo<span class="w"> </span>fdisk<span class="w"> </span>-l<span class="w"> </span>/dev/sdb
WARNING:<span class="w"> </span>GPT<span class="w"> </span><span class="o">(</span>GUID<span class="w"> </span>Partition<span class="w"> </span>Table<span class="o">)</span><span class="w"> </span>detected<span class="w"> </span>on<span class="w"> </span><span class="s1">'/dev/sdb'</span>!<span class="w"> </span>The<span class="w"> </span>util<span class="w"> </span>fdisk<span class="w"> </span>doesn<span class="err">'</span>t<span class="w"> </span>support<span class="w"> </span>GPT.<span class="w"> </span>Use<span class="w"> </span>GNU<span class="w"> </span>Parted.
Disk<span class="w"> </span>/dev/sdb:<span class="w"> </span><span class="m">2000</span>.4<span class="w"> </span>GB,<span class="w"> </span><span class="m">2000398934016</span><span class="w"> </span>bytes
<span class="m">255</span><span class="w"> </span>heads,<span class="w"> </span><span class="m">63</span><span class="w"> </span>sectors/track,<span class="w"> </span><span class="m">243201</span><span class="w"> </span>cylinders,<span class="w"> </span>total<span class="w"> </span><span class="m">3907029168</span><span class="w"> </span>sectors
<span class="nv">Units</span><span class="w"> </span><span class="o">=</span><span class="w"> </span>sectors<span class="w"> </span>of<span class="w"> </span><span class="m">1</span><span class="w"> </span>*<span class="w"> </span><span class="nv">512</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">512</span><span class="w"> </span>bytes
Sector<span class="w"> </span>size<span class="w"> </span><span class="o">(</span>logical/physical<span class="o">)</span>:<span class="w"> </span><span class="m">512</span><span class="w"> </span>bytes<span class="w"> </span>/<span class="w"> </span><span class="m">512</span><span class="w"> </span>bytes
I/O<span class="w"> </span>size<span class="w"> </span><span class="o">(</span>minimum/optimal<span class="o">)</span>:<span class="w"> </span><span class="m">512</span><span class="w"> </span>bytes<span class="w"> </span>/<span class="w"> </span><span class="m">512</span><span class="w"> </span>bytes
Disk<span class="w"> </span>identifier:<span class="w"> </span>0x00000000
<span class="w"> </span>Device<span class="w"> </span>Boot<span class="w"> </span>Start<span class="w"> </span>End<span class="w"> </span>Blocks<span class="w"> </span>Id<span class="w"> </span>System
/dev/sdb1<span class="w"> </span><span class="m">1</span><span class="w"> </span><span class="m">409639</span><span class="w"> </span><span class="m">204819</span>+<span class="w"> </span>ee<span class="w"> </span>GPT
/dev/sdb2<span class="w"> </span><span class="m">411648</span><span class="w"> </span><span class="m">1563172863</span><span class="w"> </span><span class="m">781380608</span><span class="w"> </span><span class="m">7</span><span class="w"> </span>HPFS/NTFS/exFAT
/dev/sdb3<span class="w"> </span><span class="m">1563172864</span><span class="w"> </span><span class="m">3907028991</span><span class="w"> </span><span class="m">1171928064</span><span class="w"> </span><span class="m">7</span><span class="w"> </span>HPFS/NTFS/exFAT
</code></pre></div>
<h3 id="_7">系统硬盘<a class="headerlink" href="#_7" title="Permanent link">¶</a></h3>
<p>观察:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>sudo<span class="w"> </span>fdisk<span class="w"> </span>-l<span class="w"> </span>/dev/sda
Disk<span class="w"> </span>/dev/sda:<span class="w"> </span><span class="m">1000</span>.2<span class="w"> </span>GB,<span class="w"> </span><span class="m">1000204886016</span><span class="w"> </span>bytes
<span class="m">255</span><span class="w"> </span>heads,<span class="w"> </span><span class="m">63</span><span class="w"> </span>sectors/track,<span class="w"> </span><span class="m">121601</span><span class="w"> </span>cylinders,<span class="w"> </span>total<span class="w"> </span><span class="m">1953525168</span><span class="w"> </span>sectors
<span class="nv">Units</span><span class="w"> </span><span class="o">=</span><span class="w"> </span>sectors<span class="w"> </span>of<span class="w"> </span><span class="m">1</span><span class="w"> </span>*<span class="w"> </span><span class="nv">512</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">512</span><span class="w"> </span>bytes
Sector<span class="w"> </span>size<span class="w"> </span><span class="o">(</span>logical/physical<span class="o">)</span>:<span class="w"> </span><span class="m">512</span><span class="w"> </span>bytes<span class="w"> </span>/<span class="w"> </span><span class="m">4096</span><span class="w"> </span>bytes
I/O<span class="w"> </span>size<span class="w"> </span><span class="o">(</span>minimum/optimal<span class="o">)</span>:<span class="w"> </span><span class="m">4096</span><span class="w"> </span>bytes<span class="w"> </span>/<span class="w"> </span><span class="m">4096</span><span class="w"> </span>bytes
Disk<span class="w"> </span>identifier:<span class="w"> </span>0x00000000
Disk<span class="w"> </span>/dev/sda<span class="w"> </span>doesn<span class="err">'</span>t<span class="w"> </span>contain<span class="w"> </span>a<span class="w"> </span>valid<span class="w"> </span>partition<span class="w"> </span>table
</code></pre></div>
<p>参考:</p>
<ul>
<li><a href="http://www.liusuping.com/ubuntu-linux/linux-fdisk-disk.html">使用fdisk命令对linux硬盘进行操作 - Linux/Unix - 刘苏平的博客</a></li>
<li><a href="http://blog.itpub.net/26686207/viewspace-765782/">多硬盘分区管理fdisk-张丹-leonarding-ITPUB博客</a></li>
</ul>
<p>格式化:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>sudo<span class="w"> </span>mkfs.ext4<span class="w"> </span>/dev/sda3
</code></pre></div>
<h4 id="fatab">fatab<a class="headerlink" href="#fatab" title="Permanent link">¶</a></h4>
<p>观察:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>cat<span class="w"> </span>/proc/partitions
major<span class="w"> </span>minor<span class="w"> </span><span class="c1">#blocks name</span>
<span class="w"> </span><span class="m">93</span><span class="w"> </span><span class="m">0</span><span class="w"> </span><span class="m">7520256</span><span class="w"> </span>nand
<span class="w"> </span><span class="m">93</span><span class="w"> </span><span class="m">1</span><span class="w"> </span><span class="m">65536</span><span class="w"> </span>nanda
<span class="w"> </span><span class="m">93</span><span class="w"> </span><span class="m">2</span><span class="w"> </span><span class="m">2097152</span><span class="w"> </span>nandb
<span class="w"> </span><span class="m">93</span><span class="w"> </span><span class="m">3</span><span class="w"> </span><span class="m">5341184</span><span class="w"> </span>nandc
<span class="w"> </span><span class="m">8</span><span class="w"> </span><span class="m">0</span><span class="w"> </span><span class="m">976762584</span><span class="w"> </span>sda
<span class="w"> </span><span class="m">8</span><span class="w"> </span><span class="m">1</span><span class="w"> </span><span class="m">8388608</span><span class="w"> </span>sda1
<span class="w"> </span><span class="m">8</span><span class="w"> </span><span class="m">2</span><span class="w"> </span><span class="m">2097152</span><span class="w"> </span>sda2
<span class="w"> </span><span class="m">8</span><span class="w"> </span><span class="m">3</span><span class="w"> </span><span class="m">966275800</span><span class="w"> </span>sda3
<span class="w"> </span><span class="m">8</span><span class="w"> </span><span class="m">16</span><span class="w"> </span><span class="m">1953514584</span><span class="w"> </span>sdb
<span class="w"> </span><span class="m">8</span><span class="w"> </span><span class="m">17</span><span class="w"> </span><span class="m">204800</span><span class="w"> </span>sdb1
<span class="w"> </span><span class="m">8</span><span class="w"> </span><span class="m">18</span><span class="w"> </span><span class="m">781380608</span><span class="w"> </span>sdb2
<span class="w"> </span><span class="m">8</span><span class="w"> </span><span class="m">19</span><span class="w"> </span><span class="m">1171928064</span><span class="w"> </span>sdb3
$<span class="w"> </span>sudo<span class="w"> </span>blkid
/dev/nanda:<span class="w"> </span><span class="nv">SEC_TYPE</span><span class="o">=</span><span class="s2">"msdos"</span><span class="w"> </span><span class="nv">LABEL</span><span class="o">=</span><span class="s2">"Volumn"</span><span class="w"> </span><span class="nv">TYPE</span><span class="o">=</span><span class="s2">"vfat"</span>
/dev/nandb:<span class="w"> </span><span class="nv">UUID</span><span class="o">=</span><span class="s2">"d20c81fd-3188-4650-b124-2fa090bb7920"</span><span class="w"> </span><span class="nv">TYPE</span><span class="o">=</span><span class="s2">"ext4"</span>
/dev/nandc:<span class="w"> </span><span class="nv">UUID</span><span class="o">=</span><span class="s2">"1914bbf8-2641-4b3f-a00e-4afa65d0ed8f"</span><span class="w"> </span><span class="nv">TYPE</span><span class="o">=</span><span class="s2">"ext4"</span>
/dev/sda3:<span class="w"> </span><span class="nv">UUID</span><span class="o">=</span><span class="s2">"b9db3117-90d7-48a6-8302-0b316b9745fd"</span><span class="w"> </span><span class="nv">TYPE</span><span class="o">=</span><span class="s2">"ext4"</span>
/dev/sdb1:<span class="w"> </span><span class="nv">LABEL</span><span class="o">=</span><span class="s2">"EFI"</span><span class="w"> </span><span class="nv">UUID</span><span class="o">=</span><span class="s2">"67E3-17ED"</span><span class="w"> </span><span class="nv">TYPE</span><span class="o">=</span><span class="s2">"vfat"</span>
/dev/sdb2:<span class="w"> </span><span class="nv">LABEL</span><span class="o">=</span><span class="s2">"bk4wk"</span><span class="w"> </span><span class="nv">UUID</span><span class="o">=</span><span class="s2">"52E4-78FF"</span><span class="w"> </span><span class="nv">TYPE</span><span class="o">=</span><span class="s2">"exfat"</span>
/dev/sdb3:<span class="w"> </span><span class="nv">LABEL</span><span class="o">=</span><span class="s2">"dl4p2p"</span><span class="w"> </span><span class="nv">UUID</span><span class="o">=</span><span class="s2">"52E4-7901"</span><span class="w"> </span><span class="nv">TYPE</span><span class="o">=</span><span class="s2">"exfat"</span>
</code></pre></div>
<p>参考:</p>
<ul>
<li><a href="http://name5566.com/4398.html">Cubieboard 开箱和入门 | Name5566</a></li>
<li><a href="http://www.bango29.com/cubieboard-part-1/">Cubieboard - Part 1</a></li>
</ul>
<p>配置:</p>
<div class="highlight"><pre><span></span><code>/dev/sda1 /media/ext ext4 defaults 0 2
/dev/nandc /mnt/nandc ext4 defaults 0 2
/mnt/nandc/swapfile none swap sw 0 0
/dev/sda3 /mnt/data ext4 defaults 0 2
/dev/sdb2 /mnt/bk4wk exfat rw,async,umask=0 0 0
/dev/sdb3 /mnt/dl4p2p exfat rw,async,umask=0 0 0
</code></pre></div>
<h4 id="_8">你不能在当前挂载着的分区上扩容的<a class="headerlink" href="#_8" title="Permanent link">¶</a></h4>
<p>~ <code>NoZuoNoDieWhyUtry</code></p>
<ul>
<li><a href="http://forum.cubietech.com/forum.php?mod=viewthread&tid=1772">求助,CT如何给nand分区,获得8G空间? - 上手问题 - Cubieboard中文论坛 - Powered by Discuz!</a></li>
<li>
<p><a href="http://forum.cubietech.com/forum.php?mod=viewthread&tid=1454&extra=page%3D2">求救:释放CB2 NAND 剩余空间 - 解决 - 上手问题 - Cubieboard中文论坛 - Powered by Discuz!</a></p>
<p>$ sudo nand-part -f a20 /dev/nand
check partition table copy 0: mbr: version 0x00000200, magic softw411
OK
check partition table copy 1: mbr: version 0x00000200, magic softw411
BAD!
check partition table copy 2: mbr: version 0x00000200, magic softw411
BAD!
check partition table copy 3: mbr: version 0x00000200, magic softw411
BAD!
mbr: version 0x00000200, magic softw411
3 partitions
partition 1: class = DISK, name = bootloader, partition start = 32768, partition size = 131072 user_type=0
partition 2: class = DISK, name = rootfs, partition start = 163840, partition size = 4194304 user_type=0
partition 3: class = DISK, name = UDISK, partition start = 4358144, partition size = 10584064 user_type=0</p>
</li>
</ul>
<p>等等吧,俺折腾完, CB 变码头了,才见到标题那句话!</p>
<p>才明确,想扩展内置OS 空间,要先从 SD 系统重启...所以,就算了吧...</p>
<ul>
<li><a href="http://00-00-00-00.com/2013/08/13/cubieboard%e8%87%aa%e5%8a%a8%e6%8c%82%e8%bd%bdtf%e5%8d%a1fstab%e8%ae%be%e7%bd%ae%e6%96%b9%e6%b3%95/">Cubieboard自动挂载TF卡fstab设置方法 | OPENERP-从零开始!</a></li>
</ul>
<h2 id="_9">家庭影院<a class="headerlink" href="#_9" title="Permanent link">¶</a></h2>
<p>就几点功能:</p>
<ul>
<li>自动下载</li>
<li>远程加载</li>
<li>远程播放</li>
</ul>
<h3 id="mldonkey">MLDonkey<a class="headerlink" href="#mldonkey" title="Permanent link">¶</a></h3>
<p>安装:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>agi<span class="w"> </span>-y<span class="w"> </span>mldonkey-server
</code></pre></div>
<p>就没有然后了,
启动,远程用网页控制就好,
唯一要注意的是怎么提升内网的 edonkey 为 <code>HIGH IP</code></p>
<h3 id="samba">samba<a class="headerlink" href="#samba" title="Permanent link">¶</a></h3>
<p>这是标准的跨平台文件分享服务了:</p>
<p>安装:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>agi<span class="w"> </span>-y<span class="w"> </span>samba
</code></pre></div>
<p>配置也非常直接..</p>
<h3 id="minidlna">MiniDLNA<a class="headerlink" href="#minidlna" title="Permanent link">¶</a></h3>
<p>还没有折腾...</p>
<h1 id="changelog">Changelog<a class="headerlink" href="#changelog" title="Permanent link">¶</a></h1>
<ul>
<li>140505 快速完结</li>
<li>140127 单立文章追踪</li>
</ul>如何自在的折腾QPy2014-01-26T12:42:00+08:002022-02-20T12:19:23+08:00Zoom.Quiettag:blog.zoomquiet.io,2014-01-26:/init-my-qpy-env.html
<h2 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p>QPython 知道有两年了,是看 <a href="http://book.douban.com/subject/10561367/">Head First Python(中文版) (豆瓣)</a> 时,发现竟然有
<a href="http://code.google.com/p/android-scripting/">SL4A</a></p>
<p>这种神器! Google 果断是业界良心哪,
可惜: 从<a href="http://code.google.com/p/android-scripting/downloads/list">Downloads</a>
可以看出 ,已经停 …</p>
<h2 id="_1">背景<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p>QPython 知道有两年了,是看 <a href="http://book.douban.com/subject/10561367/">Head First Python(中文版) (豆瓣)</a> 时,发现竟然有
<a href="http://code.google.com/p/android-scripting/">SL4A</a></p>
<p>这种神器! Google 果断是业界良心哪,
可惜: 从<a href="http://code.google.com/p/android-scripting/downloads/list">Downloads</a>
可以看出 ,已经停止有一年多了,目测是 Guido 叔离开后, Python 的地位在 Google
一落千丈就没有人折腾了.</p>
<p>好在旧浪两位同事, River和CF 掿起了 SL4A 的旗帜,
变成了一系列准衶器:</p>
<ul>
<li><a href="https://play.google.com/store/apps/details?id=com.hipipal.qpyplus">QPython - Python for Android - Google Play 上的 Android 应用</a></li>
<li><a href="https://play.google.com/store/apps/details?id=com.hipipal.qpy3">QPython 3 - Python3 on Android - Google Play 上的 Android 应用</a></li>
<li><a href="https://play.google.com/store/apps/details?id=com.hipipal.qpy">QPython Player for Android - Google Play 上的 Android 应用</a></li>
<li><a href="https://play.google.com/store/apps/details?id=com.hipipal.texteditor">QEdit - Code Editor in Pocket - Google Play 上的 Android 应用</a></li>
</ul>
<p>目标直指所谓的内什么,,,</p>
<p>而且,目测已经有国家高等教育项目中,
直接使用了 <code>QPython</code> 来作教学环境!</p>
<p>所以,果断要跟上用起来,,,</p>
<p>参考:</p>
<ul>
<li><a href="http://www.appannie.com/apps/amazon-appstore/top/china/education/">App Annie 的应用商店数据|Amazon排行榜中国 - Education - 2014年1月27日</a></li>
<li><a href="http://www.douban.com/group/topic/17095466/">让Python在Android系统上飞一会儿:第一节 在手机上...</a></li>
</ul>
<h2 id="_2">目标<a class="headerlink" href="#_2" title="Permanent link">¶</a></h2>
<p>哪,俺是 Pythoneer ,不是 JAVA 党,
更加是 <code>IDE 去死去死团</code> 的骨灰成员.</p>
<p>很辛苦的攒銭搞到了
<a href="http://news.mynavi.jp/news/2013/02/07/051/index.html">FILCO Majestouch MINILA</a>
青轴!
绝对不要回到 <code>一指禅</code> 的时代哪!!!</p>
<p>所以,俺要用 QPython 就是用来快速进行实用mini 应用的,
而且, 期待的开发流程, 应该完全类似现在的 web server 开发流程:</p>
<ol>
<li>本地用喜爱的编辑环境进行代码撰写 (<a href="http://www.sublimetext.com">Sublime Text 2</a>, <a href="http://leoeditor.com/">Leo</a>, etc.)</li>
<li>一键上传手机,并自动运行</li>
<li>在手机上真实操作,同时有远程日志可以实时观察,确认问题</li>
</ol>
<p>以上循环</p>
<h2 id="_3">环境准入<a class="headerlink" href="#_3" title="Permanent link">¶</a></h2>
<p>对了,以下记述充斥了各种非科普性描述,
为了误入的小伙伴不被意外恶心到,得交待一下适合继续阅读的条件:</p>
<ol>
<li>42 个月, Linux/Unix 系统使用~注意!是使用不是管理体验;不然各种标准的命令行操作要死人的,,</li>
<li>42 周的, 编程体验,不许什么語言,就是 JS 也成,起码要有一丝码感,,,</li>
<li>42 次的, 蕃茄工作时间 的经历,至少知道什么是" <a href="http://book.douban.com/reading/12671922/">心流</a>"般的专注!</li>
<li>42 天的, 相关资料通读,相关社区的加入/旁听,,,一定要摸清楚相关主要开发人员的沟通习惯 ;-)</li>
<li>42 小时, 的周边环境整备,熟悉工作系统以及配置好顺手的工具(git/apt/yum/brew ...)</li>
<li>42 分钟, 当前的空闲时间,能够专注以下描述,不会片面的抽取文字就来吼俺 <code>图样图森破</code> 什么的..</li>
<li>42 秒, 明确以上条件 <code>42%</code> 吻合,即可继续 ;-)</li>
</ol>
<h3 id="_4">硬件<a class="headerlink" href="#_4" title="Permanent link">¶</a></h3>
<p>手机: 电信协议 三星 Note2 N7108ZMDMF1:</p>
<ul>
<li>Android 4.1.1 JRO03C</li>
<li>刷的是 MIUI-3.3.15 野生版</li>
<li>CPU 四核 1.6GHz</li>
<li>内存 2G</li>
<li>存储 16G</li>
</ul>
<p>主机: MBP 12下半年版 </p>
<ul>
<li>OS X 10.9.1</li>
<li>Core i7 2.2GHz</li>
<li>8G 内存</li>
<li>500G 机械硬盘</li>
</ul>
<p>湿件: 30++++++++++岁老程序猿</p>
<ul>
<li>180,180,180,,,</li>
<li>ASP,Basic,C,C++,Clojure,Erlang,Forth,Factor,Go,Haskell,JS,JAVA,Lisp,Node,PHP,Python,Pascal,XSLT,REBOL,Rust,,,少量经验</li>
<li>精通26字母, Cnglish 熟练</li>
</ul>
<h2 id="_5">探索<a class="headerlink" href="#_5" title="Permanent link">¶</a></h2>
<p>根据策划的流程,在原作者的帮助下,进行了高强度的折腾,
经过连续 27 小时探索,基本爽了起来:</p>
<h3 id="_6">上传<a class="headerlink" href="#_6" title="Permanent link">¶</a></h3>
<p>Android 呢,就是 Linux 哪,当然应该用 <code>scp</code> 安全上传了!</p>
<p>目测,要依次解决:</p>
<ol>
<li>手机上的 <code>SSH</code> 守护在哪儿,怎么启动</li>
<li>脚本应该上传到哪儿 QPython 才能识别?</li>
</ol>
<h4 id="ssh">SSH<a class="headerlink" href="#ssh" title="Permanent link">¶</a></h4>
<p>搜索就有:</p>
<ul>
<li><a href="http://gailly.net/android/android-tips.html">Android tips</a></li>
<li><a href="http://www.linuxplanet.com/linuxplanet/reviews/7301/1">10 Android Apps for Linux Server Admins - ConnectBot, QuickSSHd, SwiFTP, AndFTP, Wyse PocketCloud - Reviews - LinuxPlanet</a></li>
<li><a href="http://my.oschina.net/winHerson/blog/84716">SSHDroid(SSH Server for Android)通过PC或命令连接android - bugeasy - 开源中国社区</a></li>
</ul>
<p>经过快速的尝试,
明确 <code>SSHDroid</code> 最简洁可用,
那就上:</p>
<p><img alt="snap4qpy" src="http://0.zoomquiet.top/CPyUG/QPython/snap/140127-qpy-sshdroid.jpg"/></p>
<ul>
<li>安装,配置都没有什么可说的</li>
<li>只是,非专业版,只能用口令登录,先忍着</li>
<li>扩展一点点儿从 <a href="http://onetimeblog.logdown.com/posts/2014/01/23/first-program-in-qpython">Hello, QPython! « one-time blog</a> 来的代码,成 <code>hollo.py</code></li>
</ul>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">androidhelper</span>
<span class="n">droid</span> <span class="o">=</span> <span class="n">androidhelper</span><span class="o">.</span><span class="n">Android</span><span class="p">()</span>
<span class="n">droid</span><span class="o">.</span><span class="n">makeToast</span><span class="p">(</span><span class="sa">u</span><span class="s1">'Hello, Username!是也乎 ;-)'</span><span class="p">)</span>
</code></pre></div>
<p>上传到哪儿呢?!</p>
<p>快速翻找一下,明确几个关键路径:</p>
<ul>
<li>
<p><code>SSHDroid</code>起始可写根:</p>
</li>
<li>
<p><code>/data/data/berserker.android.apps.sshdroid/home/</code></p>
</li>
<li>
<p>即: <code>cd ~</code> 回到的目录</p>
</li>
<li>
<p>QPython 环境分:</p>
</li>
<li>
<p>只读执行文件起点 <code>/data/data/com.hipipal.qpyplus/files/bin/</code></p>
</li>
<li>可写资源起点以及目录意义:</li>
</ul>
<div class="highlight"><pre><span></span><code>/storage/sdcard0/com.hipipal.qpyplus/
+- cache
+- lib 各Python版本的库安装入口
+- projects 俺的QPy 项目入口
+- scripts 俺的QPy 脚本入口
</code></pre></div>
<h4 id="busybox">BusyBox<a class="headerlink" href="#busybox" title="Permanent link">¶</a></h4>
<p>等等! SSH 上来后,各种不适应,这什么 shell 环境哪,连 <code>less</code>, <code>tail</code>, <code>vi</code> 都没有
好意思说自个儿是 <code>Linux</code> 嘛?!</p>
<p>搜索才知道,这货叫 <code>ash</code></p>
<ul>
<li>躲在 <code>/system/bin/sh</code> 基本上什么也不会作</li>
<li>所以,程序猿有 <a href="http://www.busybox.net/">BusyBox</a></li>
<li>一安装,批量将大堆习惯的工具,灌到 <code>system/xbin/</code></li>
</ul>
<p><img alt="snap4qpy" src="http://0.zoomquiet.top/CPyUG/QPython/snap/140126-qpy-busybox-tail.jpg"/></p>
<p>这样,才能远程观察, QPython 项目目录中,
若隐若现的 <code>.run.log</code> 明显发生什么问题,
快速增补一行:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># -*- coding: utf-8 -*-</span>
<span class="kn">import</span> <span class="nn">androidhelper</span>
<span class="n">droid</span> <span class="o">=</span> <span class="n">androidhelper</span><span class="o">.</span><span class="n">Android</span><span class="p">()</span>
<span class="n">droid</span><span class="o">.</span><span class="n">makeToast</span><span class="p">(</span><span class="sa">u</span><span class="s1">'Hello, Username!是也乎 ;-)'</span><span class="p">)</span>
</code></pre></div>
<p>就能运行成功,跳出最简单的发布公告框了!</p>
<p><img alt="snap4qpy" src="http://0.zoomquiet.top/CPyUG/QPython/snap/140126-qpy-hollo.jpg"/></p>
<h3 id="_7">运行<a class="headerlink" href="#_7" title="Permanent link">¶</a></h3>
<p>好了,进入下一个阶段: <code>怎么让 QPyhon 如系统命令一样在 ash 环境中调用我们的脚本?</code></p>
<p>目测,要依次解决:</p>
<ol>
<li>ash 环境变量是否兼容 QPython?</li>
<li>ash 环境变量如果不兼容 QPython 怎么配置?</li>
</ol>
<p>将刚刚测试明确可用的脚本从 shell 环境中调用一下:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># cd /storage/sdcard0/com.hipipal.qpyplus/projects/chaos/ </span>
<span class="c1"># /data/data/com.hipipal.qpyplus/files/bin/python hollo.py</span>
Could<span class="w"> </span>not<span class="w"> </span>find<span class="w"> </span>platform<span class="w"> </span>independent<span class="w"> </span>libraries<span class="w"> </span><prefix>
Consider<span class="w"> </span>setting<span class="w"> </span><span class="nv">$PYTHONHOME</span><span class="w"> </span>to<span class="w"> </span><prefix><span class="o">[</span>:<exec_prefix><span class="o">]</span>
ImportError:<span class="w"> </span>No<span class="w"> </span>module<span class="w"> </span>named<span class="w"> </span>site
</code></pre></div>
<p>果断没有那么简单, 检查一下系统环境:</p>
<div class="highlight"><pre><span></span><code><span class="nv">_</span><span class="o">=</span>/system/xbin/env
<span class="nv">RANDOM</span><span class="o">=</span><span class="m">25396</span>
<span class="nv">ANDROID_DATA</span><span class="o">=</span>/data
<span class="nv">BOOTCLASSPATH</span><span class="o">=</span>/system/framework/core.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/framework2.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/apache-xml.jar:/system/framework/sec_edm.jar:/system/framework/seccamera.jar
<span class="nv">PATH</span><span class="o">=</span>/data/data/berserker.android.apps.sshdroid/dropbear:/usr/bin:/usr/sbin:/bin:/sbin:/system/sbin:/system/bin:/system/xbin:/system/xbin/bb:/data/local/bin
<span class="nv">ANDROID_ROOT</span><span class="o">=</span>/system
<span class="nv">USER</span><span class="o">=</span>root
<span class="nv">LOGNAME</span><span class="o">=</span>root
<span class="nv">ANDROID_PROPERTY_WORKSPACE</span><span class="o">=</span><span class="m">9</span>,66560
<span class="nv">EXTERNAL_STORAGE</span><span class="o">=</span>/storage/sdcard0
<span class="nv">ANDROID_ASSETS</span><span class="o">=</span>/system/app
<span class="nv">SHELL</span><span class="o">=</span>/system/bin/sh
<span class="nv">TERM</span><span class="o">=</span>vt100
<span class="nv">SSH_TTY</span><span class="o">=</span>/dev/pts/1
<span class="nv">SSH_CONNECTION</span><span class="o">=</span>::ffff:192.168.0.103<span class="w"> </span><span class="m">64228</span><span class="w"> </span>::ffff:192.168.0.100<span class="w"> </span><span class="m">22</span>
<span class="nv">HOME</span><span class="o">=</span>/data/data/berserker.android.apps.sshdroid/home
<span class="nv">ANDROID_BOOTLOGO</span><span class="o">=</span><span class="m">1</span>
</code></pre></div>
<p>跟 Python 没一毛钱关系,怪不得跑不了;
吼了俩位爷,才知道: <a href="http://wiki.qpython.org/hacker/">QPython Hackers</a>
果断是依赖大堆系统环境变量的,
以往能在桌面运行起来,
也是通过 <code>大JAVA</code> 的相关接口,临时声明的!</p>
<p>那就好办了,照此办理:
<a href="https://gist.github.com/ZoomQuiet/8642464">gen_qpy_env.py</a></p>
<p><code>注意:</code> 这货一定要加载到 QPython 中,用脚本形式来跑,
如果也是从后台 shell 环境中跑,是获得不了主要关键参数的!</p>
<p><img alt="snap4qpy" src="http://0.zoomquiet.top/CPyUG/QPython/snap/140126-qpy-gen-profile.jpg"/></p>
<p>然后!? 肿么,让 shell 环境每次都能自动加载上这堆配置?</p>
<p>综合,搜索来的相关说明:</p>
<ul>
<li><a href="http://www.cnblogs.com/shyang--TechBlogs/archive/2011/10/27/2226664.html">[转]linux虚拟内核文件系统介绍 - shy.ang - 博客园</a></li>
<li><a href="http://www.xdracco.net/mount-android-system-partition-with-readwrite-access/">Mount Android System Partition With Read/Rrite Access</a></li>
<li><a href="http://gailly.net/android/android-tips.html">Android tips</a> </li>
</ul>
<p>经过尝试,明确这么来:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># mount -o remount,rw /dev/block/mtdblock3 /system</span>
<span class="c1"># ln -s /storage/sdcard0/com.hipipal.qpyplus/projects/qpy_profile /etc/profile</span>
<span class="c1"># mount -o remount,ro /dev/block/mtdblock3 /system</span>
</code></pre></div>
<p>再关闭,重启 <code>SSHDroid</code> 后,远程登入,测试:</p>
<p><img alt="snap4qpy" src="http://0.zoomquiet.top/CPyUG/QPython/snap/140126-qpy-this-zen.png"/></p>
<p>然后,远程人工从 shell 调用</p>
<div class="highlight"><pre><span></span><code><span class="c1"># cd /storage/sdcard0/com.hipipal.qpyplus/projects/chaos/ </span>
<span class="c1"># /data/data/com.hipipal.qpyplus/files/bin/python hollo.py</span>
</code></pre></div>
<p>手机无论在什么桌面,都能跳出来俺的 <code>hollo.py</code> 运行结果:</p>
<p><img alt="snap4qpy" src="http://0.zoomquiet.top/CPyUG/QPython/snap/140126-qpy-console-hollo.jpg"/></p>
<p>然后,本地,习惯性的,就可以用 <a href="http://tmux.sourceforge.net/">tmux</a> 同时
观察/管理本地以及远程的开发/测试/运行情况了:</p>
<p><img alt="snap4qpy" src="http://0.zoomquiet.top/CPyUG/QPython/snap/140127-qpy-tumx.png"/></p>
<h4 id="beta">BETA乱入<a class="headerlink" href="#beta" title="Permanent link">¶</a></h4>
<p>作者看俺这么努力的折腾从内部机密放送俺最新开发版本,兴奋的安装上:</p>
<p><img alt="snap4qpy" src="http://0.zoomquiet.top/CPyUG/QPython/snap/140127-qpy-new-version.jpg"/></p>
<p>然后,再运行...</p>
<div class="highlight"><pre><span></span><code>Traceback<span class="w"> </span><span class="o">(</span>most<span class="w"> </span>recent<span class="w"> </span>call<span class="w"> </span>last<span class="o">)</span>:
<span class="w"> </span>File<span class="w"> </span><span class="s2">"/storage/sdcard0/com.hipipal.qpyplus/projects/chaos/hollo.py"</span>,<span class="w"> </span>line<span class="w"> </span><span class="m">3</span>,<span class="w"> </span><span class="k">in</span><span class="w"> </span><module>
<span class="w"> </span><span class="nv">droid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span>androidhelper.Android<span class="o">()</span>
<span class="w"> </span>File<span class="w"> </span><span class="s2">"tubelib/sl4a.py"</span>,<span class="w"> </span>line<span class="w"> </span><span class="m">34</span>,<span class="w"> </span><span class="k">in</span><span class="w"> </span>__init__
<span class="w"> </span>self.conn<span class="w"> </span><span class="o">=</span><span class="w"> </span>socket.create_connection<span class="o">(</span>addr<span class="o">)</span>
<span class="w"> </span>File<span class="w"> </span><span class="s2">"/home/river/android-sdk/workplace/python-for-android/build/python-install/lib/python2.7/socket.py"</span>,<span class="w"> </span>line<span class="w"> </span><span class="m">571</span>,<span class="w"> </span><span class="k">in</span><span class="w"> </span>create_connection
socket.error:<span class="w"> </span><span class="o">[</span>Errno<span class="w"> </span><span class="m">111</span><span class="o">]</span><span class="w"> </span>Connection<span class="w"> </span>refused
</code></pre></div>
<p><code>/home/river/android-sdk/workplace</code> 囧rz...</p>
<p>什么东西?! 怎么超出来原作的本地目录了?!</p>
<p>再问,才知道:</p>
<ul>
<li><code>AP_HANDSHAKE=5873cf77-e70b-4887-a8b2-28b7db3c408e</code></li>
<li>类似 <code>AP_</code> 前缀的系列环境变量是随发行版,每次不同的,</li>
<li>必须匹配上,否则,系统找不到,就只能使用缓存的不知哪儿的路径了...</li>
</ul>
<p>所以,必须:</p>
<ul>
<li>
<p>从项目中打开脚本:
<img alt="snap4qpy" src="http://0.zoomquiet.top/CPyUG/QPython/snap/140127-qpy-env-proj.jpg"/></p>
</li>
<li>
<p>从 QEditor 中运行
<img alt="snap4qpy" src="http://0.zoomquiet.top/CPyUG/QPython/snap/140127-qpy-env-run.jpg"/></p>
</li>
<li>
<p>在 console 中生成:
<img alt="snap4qpy" src="http://0.zoomquiet.top/CPyUG/QPython/snap/140127-qpy-env-gen-again.jpg"/></p>
</li>
</ul>
<h4 id="qpython">QPython头声明<a class="headerlink" href="#qpython" title="Permanent link">¶</a></h4>
<p>参考: <a href="http://wiki.qpython.org/doc/program_guide/#qpython-header">Programming Guide</a></p>
<p>脚本第一行的不同声明,将由 QPython 智能识别给予不同的运行环境,一定要理解:</p>
<ul>
<li><code>#qpy:console</code> , 是指运行环境为 QPython 的命令行环境</li>
<li><code>#qpy:2</code> 是指运行环境为 QPython 2 的命令行环境</li>
<li><code>#qpy:3</code> 是指运行环境为 QPython 3 的命令行环境</li>
<li>没有 <code>#qpy:*</code> 的是指基于 <a href="http://kylelk.github.io/html-examples/androidhelper.html">SL4A</a> 的GUI 依赖环境</li>
<li>
<p>2014 追加支持的</p>
<h1 id="qpywebapp">qpy:webapp:<app title=""><a class="headerlink" href="#qpywebapp" title="Permanent link">¶</a></app></h1>
<h1 id="qpyfullscreen">qpy:fullscreen<a class="headerlink" href="#qpyfullscreen" title="Permanent link">¶</a></h1>
<h1 id="qpylocalhost8080">qpy://localhost:8080<a class="headerlink" href="#qpylocalhost8080" title="Permanent link">¶</a></h1>
<p>"""
Launching the web service on localhost:8080
without android titlebar (fullscreen)
"""</p>
</li>
</ul>
<h3 id="_8">自动<a class="headerlink" href="#_8" title="Permanent link">¶</a></h3>
<p>好了,进入最后一个阶段: <code>怎么让所有的上传->配置->运行->日志收集 全部自动化一键完成?</code></p>
<p>目测,要依次解决:</p>
<ol>
<li>自动上传?!(怎么通过公匙的部署,来达到无口令远程登录手机?)</li>
<li>自动运行手机端的脚本?!</li>
<li>自动收集日志?</li>
</ol>
<p>问题一,参考:</p>
<ul>
<li><a href="http://stackoverflow.com/questions/8291380/how-to-get-fabric-to-automatically-instead-of-user-interactively-interact-with/10007635#10007635">python - How to get Fabric to automatically (instead of user-interactively) interact with shell commands? Combine with pexpect? - Stack Overflow</a></li>
<li><a href="http://ilogue.com/jasper/blog/fexpect--dealing-with-prompts-in-fabric-with-pexpect/">Fexpect adds answering to prompts to fabric with use of pexpect</a></li>
<li><a href="http://www.noah.org/wiki/pexpect">pexpect - Noah.org</a></li>
</ul>
<p>总之,对口令,没有什么好办法,大家都是通过获取反馈,匹配期待,自动输入...</p>
<p>只是,这样折腾,很扯蛋! 用口令登录的安全隐患怎么强调都不过份!</p>
<p>何况,通过 RSA/DSA 密匙对加密,公匙部署,自动双向加密,
安定,稳定,方便的用了多少年?!</p>
<p>没理由在 Android 这儿栽了哪!
果断的: </p>
<ul>
<li>先将本地公匙用口令登录的方式推上手机</li>
<li>然后,<a href="http://0.zoomquiet.top/CPyUG/QPython/apk/berserker.android.apps.sshdroid-cracked-signed.apk">sshdroid-cracked.apk</a></li>
<li>然后,就没有然后了 ;-)</li>
</ul>
<p>只是,唯一的问题:
- 因为 SSH 服务端切换了, 导致 SSH 认证冲突,要清除对应的配置行
- 每次都要全部清除,或是人工清除?
- 不用这么 Naive ,参考:<a href="http://floss.qiniudn.com/data/20130327153058/index.html">SSH Warning: the RSA host key for differs from the key for the IP address - zhangp专栏</a></p>
<p>一行解决:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>sed<span class="w"> </span>-i<span class="w"> </span>-e<span class="w"> </span><span class="s1">'36d'</span><span class="w"> </span>~/.ssh/known_hosts
</code></pre></div>
<h4 id="fabric"><a href="http://docs.fabfile.org/en/1.5/index.html#usage-documentation">Fabric</a><a class="headerlink" href="#fabric" title="Permanent link">¶</a></h4>
<p>非 <code>C/S</code> 结构的脚本化自动部署工具!</p>
<p>嘦在本地安装好<a href="http://docs.fabfile.org/en/1.5/index.html#usage-documentation">Fabric</a>
再在本地工程目录中放一个 <code>fabfile.py</code>, 就可以:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>fab<span class="w"> </span>?
Warning:<span class="w"> </span>Command<span class="o">(</span>s<span class="o">)</span><span class="w"> </span>not<span class="w"> </span>found:
<span class="w"> </span>?
Available<span class="w"> </span>commands:
<span class="w"> </span>env<span class="w"> </span>print<span class="w"> </span>Android<span class="w"> </span>sys.<span class="w"> </span>env
<span class="w"> </span>genenv<span class="w"> </span>gen<span class="w"> </span>qpy<span class="w"> </span>need<span class="w"> </span>env<span class="w"> </span>into:<span class="w"> </span>/storage/sdcard0/com.hipipal.qpyplus/projects/qpy_profile
<span class="w"> </span>pushproj<span class="w"> </span>scp<span class="w"> </span>all<span class="w"> </span>.py<span class="w"> </span>into<span class="w"> </span>Android<span class="w"> </span>QPython<span class="w"> </span>projects<span class="w"> </span>dir
<span class="w"> </span>qpy<span class="w"> </span>main<span class="w"> </span>develop<span class="w"> </span>tools,<span class="w"> </span>auto<span class="w"> </span>upload<span class="w"> </span>and<span class="w"> </span>running<span class="w"> </span><span class="k">in</span><span class="w"> </span>Android
<span class="w"> </span>qpy_run_it<span class="w"> </span>fab<span class="w"> </span>qpy_run_it:script<span class="o">=</span>MY.py
<span class="w"> </span>uname<span class="w"> </span>print<span class="w"> </span>Android<span class="w"> </span>sys.<span class="w"> </span>info.
</code></pre></div>
<p>日常,无论折腾多少个项目,都可以统一部署此脚本到目录中,
<a href="https://gist.github.com/ZoomQuiet/8645207">Fabric for QPython auto upload/running script/collect log etc... from local through SSH</a></p>
<p>只要定制一两只参数, 平时的开发流程就变成了:</p>
<ol>
<li>本地用喜爱的编辑环境进行代码撰写 (<a href="http://www.sublimetext.com">Sublime Text 2</a>, <a href="http://leoeditor.com/">Leo</a>, etc.)</li>
<li><code>fab qpy:script=当前调试的主脚本.py</code> 一键上传手机,并自动运行</li>
<li>在手机上真实操作,明确效果</li>
</ol>
<h4 id="_9">日志<a class="headerlink" href="#_9" title="Permanent link">¶</a></h4>
<p>目测同最初设想的理想开发流程相比:</p>
<div class="highlight"><pre><span></span><code>1. 本地用喜爱的编辑环境进行代码撰写
2. 一键上传手机,并自动运行
3. 在手机上真实操作,同时有远程日志可以实时观察,确认问题
</code></pre></div>
<p>只差一个运行日志的实时观察了哪,,,</p>
<p>本来想着很简洁的:</p>
<ul>
<li><a href="http://tmux.sourceforge.net/">tmux</a> 再多开个窗口</li>
<li><code>tail -f /PATH/2/MY/QPY/PROJECT/.run.log</code> 就完事儿的哪!</li>
</ul>
<p>结果,不得不提交个 Issue:</p>
<p><a href="https://github.com/qpython-android/QPython.org/issues/2">.run.log is odd · Issue #2 · qpython-android/QPython.org</a></p>
<h2 id="_10">结论<a class="headerlink" href="#_10" title="Permanent link">¶</a></h2>
<p>虽然, 最后集中成了一份儿
<a href="https://gist.github.com/ZoomQuiet/8645207">fabfile.py</a>
脚本,但是涉及的工具还是很多的,
所以, 整体上,最终可用的组合关系是:</p>
<div class="highlight"><pre><span></span><code><span class="k">[[Android in mobile]]</span>
<span class="w"> </span><span class="na">+- /etc/profile -> ln -s</span>
<span class="w"> </span><span class="na">| V</span>
<span class="w"> </span><span class="na">| V</span>
<span class="w"> </span><span class="na">| /storage/sdcard0/com.hipipal.qpyplus/projects/qpy_profil</span>
<span class="w"> </span><span class="na">| ^</span>
<span class="w"> </span><span class="na">| ^</span>
<span class="w"> </span><span class="na">+- QPython -> gen_qpy_env.py</span>
<span class="w"> </span><span class="na">| .../projects/MyProject</span>
<span class="w"> </span><span class="na">| ^</span>
<span class="w"> </span><span class="na">| ^</span>
<span class="w"> </span><span class="na">| ^</span>
<span class="w"> </span><span class="na">`- SSHDriod + id_rsa.pub</span>
<span class="w"> </span><span class="na">^</span>
<span class="w"> </span><span class="na">^ scp,and run()</span>
<span class="w"> </span><span class="na">^</span>
<span class="w"> </span><span class="na">/-> base fabfile.py</span>
<span class="w"> </span><span class="na">|</span>
<span class="w"> </span><span class="na">+- Fabric</span>
<span class="w"> </span><span class="na">+- pip</span>
<span class="w"> </span><span class="na">+- Python</span>
<span class="w"> </span><span class="na">|</span>
<span class="k">[[MBP in local]]</span>
<span class="na">all in same wifi net domain</span>
</code></pre></div>
<h3 id="todo">TODO<a class="headerlink" href="#todo" title="Permanent link">¶</a></h3>
<p>然后, 有个比较顺心的 QPython 折腾环境了,
就可以进一步的折腾各种想玩/能玩能玩的了!</p>
<h3 id="pip">pip<a class="headerlink" href="#pip" title="Permanent link">¶</a></h3>
<p>没有 pip 的世界是艰难的世界,所以,,,</p>
<p><a href="http://www.pip-installer.org/en/latest/installing.html">Installation — pip 1.5.2 documentation</a></p>
<div class="highlight"><pre><span></span><code><span class="c1"># python get-pip.py</span>
Traceback<span class="w"> </span><span class="o">(</span>most<span class="w"> </span>recent<span class="w"> </span>call<span class="w"> </span>last<span class="o">)</span>:
<span class="w"> </span>File<span class="w"> </span><span class="s2">"get-pip.py"</span>,<span class="w"> </span>line<span class="w"> </span><span class="m">21343</span>,<span class="w"> </span><span class="k">in</span><span class="w"> </span><module>
<span class="w"> </span>import<span class="w"> </span>bz2
ImportError:<span class="w"> </span>No<span class="w"> </span>module<span class="w"> </span>named<span class="w"> </span>bz2
</code></pre></div>
<p>那么回到老方式, <code>setuptools->easy_install pip->pip</code>
<a href="https://pypi.python.org/pypi/setuptools#installation-instructions">setuptools 2.1 : Python Package Index</a></p>
<div class="highlight"><pre><span></span><code><span class="c1"># python ez_setup.py</span>
Downloading<span class="w"> </span>https://pypi.python.org/packages/source/s/setuptools/setuptools-2.1.tar.gz
Extracting<span class="w"> </span><span class="k">in</span><span class="w"> </span>/storage/sdcard0/com.hipipal.qpyplus/cache/tmpCpG6N8
Now<span class="w"> </span>working<span class="w"> </span><span class="k">in</span><span class="w"> </span>/storage/sdcard0/com.hipipal.qpyplus/cache/tmpCpG6N8/setuptools-2.1
Installing<span class="w"> </span>Setuptools
Traceback<span class="w"> </span><span class="o">(</span>most<span class="w"> </span>recent<span class="w"> </span>call<span class="w"> </span>last<span class="o">)</span>:
<span class="w"> </span>File<span class="w"> </span><span class="s2">"setup.py"</span>,<span class="w"> </span>line<span class="w"> </span><span class="m">28</span>,<span class="w"> </span><span class="k">in</span><span class="w"> </span><module>
<span class="w"> </span>from<span class="w"> </span>setuptools.command.test<span class="w"> </span>import<span class="w"> </span><span class="nb">test</span><span class="w"> </span>as<span class="w"> </span>_test
<span class="w"> </span>File<span class="w"> </span><span class="s2">"/storage/sdcard0/com.hipipal.qpyplus/cache/tmpCpG6N8/setuptools-2.1/setuptools/command/test.py"</span>,<span class="w"> </span>line<span class="w"> </span><span class="m">6</span>,<span class="w"> </span><span class="k">in</span><span class="w"> </span><module>
<span class="w"> </span>from<span class="w"> </span>unittest<span class="w"> </span>import<span class="w"> </span>TestLoader,<span class="w"> </span>main
ImportError:<span class="w"> </span>No<span class="w"> </span>module<span class="w"> </span>named<span class="w"> </span>unittest
Something<span class="w"> </span>went<span class="w"> </span>wrong<span class="w"> </span>during<span class="w"> </span>the<span class="w"> </span>installation.
See<span class="w"> </span>the<span class="w"> </span>error<span class="w"> </span>message<span class="w"> </span>above.
</code></pre></div>
<p>好吧,只能先放下了,
但是,没有 pip 怎么安装上 <a href="http://mercurial.selenic.com/">Mercurial</a> 呢?</p>
<p>有了 <a href="http://mercurial.selenic.com/">Hg</a> 才真正海阔天空了呢...</p>
<h3 id="restful-onering">RESTful "OneRing"<a class="headerlink" href="#restful-onering" title="Permanent link">¶</a></h3>
<p>不知道大家记得 <a href="http://code.google.com/p/onering-desktop/wiki/OneRing">OneRing</a>
卟?!</p>
<p>豆瓣首席架构师/布道官/CTO 洪教授 亲手玩的项目:</p>
<div class="highlight"><pre><span></span><code>跨平台的桌面应用开发库,
使用HTML5+CSS3制作用户界面,
用Javascript编写交互逻辑,
同时提供用写web后端的技术编写后台逻辑!
</code></pre></div>
<p>但素,现在有了 QPython 完全可以0成本山寨一个移动版的 MyRing 了哪:</p>
<p>呼应各种本地的 <a href="http://floss.qiniudn.com/data/20110818160723/index.html">RESTful</a>
请求,总是要有一个内置的web 服务的,</p>
<p>当然上
<a href="http://bottlepy.org/">Bottle</a>
了,只有一个文件的越级微框架,不用安装,随项目目录发布就好.</p>
<div class="highlight"><pre><span></span><code><span class="c1">#qpy:console</span>
<span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">run</span><span class="p">,</span> <span class="n">template</span>
<span class="nd">@route</span><span class="p">(</span><span class="s1">'/hello/<name>'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">index</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
<span class="k">return</span> <span class="n">template</span><span class="p">(</span><span class="s1">'<b>Hello {{name}}</b>!'</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">name</span><span class="p">)</span>
<span class="n">run</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s1">'localhost'</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">8080</span><span class="p">)</span>
</code></pre></div>
<p>因为是要守护在后台长期运行的,所以用 <code>#qpy:console</code> 标定</p>
<p>可惜:</p>
<p><img alt="snap4qpy" src="http://0.zoomquiet.top/CPyUG/QPython/snap/140126-qpy-bottle-error.jpg"/></p>
<p>原来:</p>
<p><img alt="snap4qpy" src="http://0.zoomquiet.top/CPyUG/QPython/snap/140126-qpy-install-wsgi.jpg"/></p>
<p>然后:</p>
<p><img alt="snap4qpy" src="http://0.zoomquiet.top/CPyUG/QPython/snap/140126-qpy-bottle-running.jpg"/></p>
<p>没有然后:</p>
<p><img alt="snap4qpy" src="http://0.zoomquiet.top/CPyUG/QPython/snap/140126-qpy-bottle-hello.jpg"/></p>
<p>哈哈! 一切如愿!</p>
<h2 id="_11">专题体例:<a class="headerlink" href="#_11" title="Permanent link">¶</a></h2>
<p>QPy 的大妈们曰了: 每个专题应该包括 </p>
<div class="highlight"><pre><span></span><code><span class="nx">Introduction</span><span class="p">,</span><span class="w"> </span>
<span class="nx">getting</span><span class="w"> </span><span class="nx">start</span><span class="p">(</span><span class="nx">include</span><span class="w"> </span><span class="nx">sample</span><span class="w"> </span><span class="nx">better</span><span class="p">),</span><span class="w"> </span>
<span class="nx">packages</span><span class="p">,</span><span class="w"> </span>
<span class="nx">videos</span><span class="w"> </span><span class="p">(</span><span class="nx">searched</span><span class="w"> </span><span class="nx">result</span><span class="w"> </span><span class="nx">from</span><span class="w"> </span><span class="nx">youtube</span><span class="w"> </span><span class="k">or</span><span class="w"> </span><span class="nx">directly</span><span class="w"> </span><span class="nx">video</span><span class="w"> </span><span class="nx">link</span><span class="w"> </span><span class="p">)</span>
</code></pre></div>
<p>好吧,慢慢来,,,下次专注 Bottle 结合 QPython 实现可用随身小工具.</p>
<h2 id="_12">时间帐单:<a class="headerlink" href="#_12" title="Permanent link">¶</a></h2>
<p>简单回顾一下整个从完全小白到折腾出当前扫盲文章的时间投入:</p>
<ul>
<li>1H: 动心,所有相关资料收集,概览</li>
<li>2H: SSH 登录成功, 不用口令,未果</li>
<li>2H: env 确认问题,解决问题</li>
<li>1H: BusyBox 熟悉手机上的shell 环境</li>
<li>8H: Fabric 打通, 还是env 问题,以及版本变化后要重新生成 env 配置</li>
<li>4H: 整理为文章</li>
</ul>
<p><code>18H</code> 总计可统计的大块时间, 其它基本有几乎相同的沟通时间,用在
通过 微信/邮件/github 等等方式沟通</p>
<h2 id="changelog">Changelog<a class="headerlink" href="#changelog" title="Permanent link">¶</a></h2>
<ul>
<li>171011 ZQ 迁移到 .io 私人域名中<ul>
<li>官方文档-> <a href="http://www.qpython.org/document.html">Welcome to read the QPython guide! — QPython 0.9 documentation</a></li>
</ul>
</li>
<li>140127 ZQ 增补所有细节</li>
<li>140126 ZQ 创建</li>
</ul>迁出RTFD.org2014-01-19T00:00:00+08:002014-05-05T11:12:50+08:00Zoom.Quiettag:blog.zoomquiet.io,2014-01-19:/jump-into-7niu.html
<h1 id="rtfdorg">RTFD.org<a class="headerlink" href="#rtfdorg" title="Permanent link">¶</a></h1>
<ul>
<li>正名 readthedocs.org</li>
<li>别名儿 <code>RTFD</code>.org</li>
</ul>
<p>是一个良心服务, 自动将指定的任何一个仓库中的 Sphinx 工程,
根据提交事件,自动同步,编译,发布.</p>
<p>完 …</p>
<h1 id="rtfdorg">RTFD.org<a class="headerlink" href="#rtfdorg" title="Permanent link">¶</a></h1>
<ul>
<li>正名 readthedocs.org</li>
<li>别名儿 <code>RTFD</code>.org</li>
</ul>
<p>是一个良心服务, 自动将指定的任何一个仓库中的 Sphinx 工程,
根据提交事件,自动同步,编译,发布.</p>
<p>完全 0 配置,以及不占用大家的任何网络资源,完全免费!</p>
<h2 id="_1">原先<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p>发现后,高兴的大规模使用中,并配置了 Disqus 等等好物...</p>
<h2 id="_2">现在<a class="headerlink" href="#_2" title="Permanent link">¶</a></h2>
<p><img alt="d005a8bd08c1" src="https://f.cloud.github.com/assets/834231/1538179/849551c2-4cdc-11e3-9759-d005a8bd08c1.jpg"/></p>
<ul>
<li><a href="https://github.com/rtfd/readthedocs.org/issues/435">Many builds stuck in "triggered" state · Issue #435 · rtfd/readthedocs.org</a></li>
<li><a href="https://github.com/rtfd/readthedocs.org/issues/592">how stop a build triggered from long time ago with finish · Issue #592 · rtfd/readthedocs.org</a></li>
</ul>
<p>突然有一天,所有图书都不编译了,卡在了哪儿,
四处一问才发现是大规模事件,
一时解决不了.</p>
<h2 id="_3">然后<a class="headerlink" href="#_3" title="Permanent link">¶</a></h2>
<p><a href="http://techparty.org/events/2013/12/29/et-ecugcon-sz/">无责任报道~ECUG2013Con</a>
知道了 7牛, 自然的就想从国外的良心服务,迁移到国内的良心服务;</p>
<h3 id="_4">迁移是愉快的<a class="headerlink" href="#_4" title="Permanent link">¶</a></h3>
<ul>
<li>开辟 bucket</li>
<li>配置本地 <code>.conf</code></li>
<li>配置本地自动同步脚本</li>
</ul>
<p>run!</p>
<h3 id="_5">域名是绑定不了的<a class="headerlink" href="#_5" title="Permanent link">¶</a></h3>
<p>当然,发布出来都是:</p>
<ul>
<li>chaos2.qiniudn.com</li>
<li>rtfd.qiniudn.com</li>
</ul>
<p>这样的,想使用自个儿的域名,结果: </p>
<ul>
<li><a href="http://segmentfault.com/q/1010000000386448">无法使用交通银行支持!</a></li>
<li><a href="http://segmentfault.com/q/1010000000386461">是否可能支持大目录的 Bucket 间迁移? - 七牛云存储问答 - SegmentFault</a></li>
</ul>
<p>更加杯具的是:</p>
<div class="highlight"><pre><span></span><code>chaos.zoomquiet.io 自定义 审核失败 京ICP备09067992号
状态说明: 2014-01-21 11:32:36 审核失败。域名未备案
</code></pre></div>
<p>绑定的域名必须有备案!</p>
<h2 id="_6">是也乎<a class="headerlink" href="#_6" title="Permanent link">¶</a></h2>
<p>好吧,,,俺只有在自个儿的主机上用 Nginx 进行反向代理了...</p>
<h1 id="changelog">Changelog<a class="headerlink" href="#changelog" title="Permanent link">¶</a></h1>
<ul>
<li>140119 开始总结</li>
</ul>CBInstallfest 的体验2014-01-11T00:00:00+08:002014-01-27T23:56:50+08:00Zoom.Quiettag:blog.zoomquiet.io,2014-01-11:/cbi-zq-install.html
<h2 id="cbi">CBI<a class="headerlink" href="#cbi" title="Permanent link">¶</a></h2>
<p><a href="http://blog.zhgdg.org/2014-01/et-cbi1/">CBInstall.1 欢乐完成</a>
记要了现场活动的情况;</p>
<p>当然,俺也是学员之一,要交作业的,所以,俺的刷机笔记如下:</p>
<h2 id="_1">目标<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p>用CB3 替代原先的 …</p>
<h2 id="cbi">CBI<a class="headerlink" href="#cbi" title="Permanent link">¶</a></h2>
<p><a href="http://blog.zhgdg.org/2014-01/et-cbi1/">CBInstall.1 欢乐完成</a>
记要了现场活动的情况;</p>
<p>当然,俺也是学员之一,要交作业的,所以,俺的刷机笔记如下:</p>
<h2 id="_1">目标<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
<p>用CB3 替代原先的兼容 PC 机作家庭服务器!</p>
<h2 id="_2">环境<a class="headerlink" href="#_2" title="Permanent link">¶</a></h2>
<ul>
<li>MBP 11年下半年版, 15吋</li>
<li>MAC OS X 10.9 Mavericks</li>
<li>CB3(CubieTruck) 以及套件的配件</li>
</ul>
<h2 id="_3">刷机<a class="headerlink" href="#_3" title="Permanent link">¶</a></h2>
<p>果然如宣传的,是那么简单!</p>
<ol>
<li>准备工具 ~ <a href="http://docs.cubieboard.org/tutorials/common/livesuit_installation_guide">LiveSuit</a> </li>
<li>下载镜像 ~ <a href="http://dl.cubieboard.org/software">NAND镜像</a></li>
<li>刷机</li>
</ol>
<p>尝试了 arch linux 的镜像,发觉进入后包管理命令,完全不熟悉,所以,只好坚持使用 Ubuntu了.</p>
<h3 id="_4">细节<a class="headerlink" href="#_4" title="Permanent link">¶</a></h3>
<ul>
<li><a href="http://docs.cubieboard.org/tutorials/common/livesuit_installation_guide">LiveSuit</a> 真心傻瓜,在MAC 上完全无碍!</li>
</ul>
<p><img alt="livesuit_mac" src="http://zoomq.qiniudn.com/ZHGDG/2014/140111-CBInstallfest.1/livesuit_mac.png"/></p>
<ul>
<li>
<p>下载时,为了大家的幸福,不要下载 .img 的文件,下载压缩的 .gz 文档本地解开就好</p>
<p>$ 7z x lubuntu-server-nand.img.gz</p>
</li>
<li>
<p>为了防止手指意外的摸到带电元件,应该先将赠送的PV板安装上,注意:
<img alt="cubietruck_fel_button" src="http://dyhr.com/wp-content/uploads/Cubietruck_FEL_button-300x224.jpg"/></p>
<ul>
<li>正确的次序</li>
<li>以及要将板上的保护膜清除</li>
<li>另外,应该用 CB 驱动激光雕刻仪,来给每个PV 板刻上 CB小猴纸的 logo ,建议已经严正向 Benn 吼过了</li>
</ul>
</li>
<li>
<p>刷机时, <code>FEL</code> 键-USB线-电脑的先后顺序:</p>
<ol>
<li>电脑里先运行 LiveSuit 并加载目标NAND 镜像</li>
<li>按住<code>FEL</code> 键,不松,然后插入USB线</li>
<li>再将 USB线插入电脑</li>
<li>然后松开 <code>FEL</code> 键</li>
<li>LiveSuit 识别外部 CB 板,开始请求确认,准备好开始刷机了</li>
</ol>
</li>
<li>
<p>刷机一般5分钟以内就可以完成:</p>
<ul>
<li>LiveSute 进度 100% 提示已经完成</li>
<li>CB 板上的几个 LED 灯开始闪动</li>
<li>这时,可以长按板上的 <code>POWER ON</code> 键,进行热关闭</li>
<li>等板上的灯都更灭时,代表 CB 已经加载的系统完全终止运行</li>
<li>这时就可以拔下 USB 线了</li>
<li>再将 CB 的电源插入,刷好的系统就真正自举运行起来了!</li>
</ul>
</li>
<li>
<p>首次启动系统时, Ubuntu 会尝试获得当前的网络IP, 而且过期时间定为60秒,我们就只能安静的等哈等! </p>
<ul>
<li>这绝对是应该优化的默认配置.</li>
</ul>
</li>
</ul>
<p><img alt="ct_default_py.png(PNG 图像,814x201 像素)" src="http://zoomq.qiniudn.com/ZHGDG/2014/140111-CBInstallfest.1/ct_default_py.png"/></p>
<ul>
<li>默认安装了Python 点赞!</li>
</ul>
<h2 id="_5">问题<a class="headerlink" href="#_5" title="Permanent link">¶</a></h2>
<ol>
<li>
<p>对于可以通过内核接口,调整板上 LED 灯的事儿</p>
<ul>
<li>这么有趣,为毛不给出对应的文档?</li>
</ul>
</li>
<li>
<p>两次都上了 Nand 镜像文件名的当! 比如: </p>
<p>:::text
http://dl.cubieboard.org/software/a20-cubietruck/lubuntu/ \
ct-lubuntu-nand-v1.01/ct-lubuntu-server/lubuntu-server-nand.img.gz
ct-lubuntu-nand-v1.00/ct-lubuntu-server-20131026/lubuntu-server-nand.img.gz
ct-lubuntu-nand-v1.00/VGA/lubuntu-server-nand.img.gz</p>
</li>
</ol>
<p>从下载路径的确可以看出是针对什么的镜像;
但是,无论哪种版本的镜像, lubuntu 的下载下来
都是 <code>lubuntu-server-nand.img.gz</code>
解压缩 也都是 <code>lubuntu-server-nand.img</code>
根本就看不出什么是什么了!
强烈建议,重新制定版本规范,也包含最终下载文件名;比如:</p>
<div class="highlight"><pre><span></span><code>ct-lubuntu-13.06-server-nand.img.gz
ct-vga-lubuntu-13.06-server-nand.img.gz
</code></pre></div>
<h3 id="vga">VGA<a class="headerlink" href="#vga" title="Permanent link">¶</a></h3>
<p>是的,兴冲冲,回家准备接上网络,开始家庭服务器的配置!
结果发现,5年前的液瞐屏幕接上没有反应!
再扛来老婆的新液瞐屏也是只有间或的白色闪线,没有信号输出!</p>
<p>这就要了亲命! </p>
<ul>
<li>命令行上加载驱动,启动wifi 接入家庭无线网络,不是不行,只是没必要,因为以后的正当运行环境是拉网线的</li>
<li>然而,网络和能接 HDMI 的液瞐电视不是一房,没办法现拉根网线去</li>
</ul>
<p>所以,果断 google 之!
果然,是常见问题! 居然 VGA 的输出是需要特殊系统镜像的!</p>
<p>这也才发现, CB3 的 VGA 支持系统镜像,居然只有在 <code>lubuntu-nand-v1.00</code> 中有,
<code>lubuntu-nand-v1.01</code> 中还没有完成兼容!</p>
<p>重新刷上对口的 OS, 这下子终于见到熟悉的命令行界面了!!!</p>
<p>但是:</p>
<div class="highlight"><pre><span></span><code>Welcome to Linaro 13.08 (GNU/Linux 3.4.61+ armv7l)
* Documentation: https://wiki.linaro.org/
New release '13.10' available.
Run 'do-release-upgrade' to upgrade to it.
</code></pre></div>
<p>这倒底是升级呢? 还是不升级呢?!</p>
<h3 id="ip">IP<a class="headerlink" href="#ip" title="Permanent link">¶</a></h3>
<p>修订: <code>/etc/network/interfaces</code> 为:</p>
<div class="highlight"><pre><span></span><code>auto<span class="w"> </span>lo<span class="w"> </span>eth0
iface<span class="w"> </span>lo<span class="w"> </span>inet<span class="w"> </span>loopback
<span class="c1">#iface eth0 inet dhcp</span>
iface<span class="w"> </span>eth0<span class="w"> </span>inet<span class="w"> </span>static
address<span class="w"> </span><span class="m">192</span>.168.0.111
gateway<span class="w"> </span><span class="m">192</span>.168.0.1
netmask<span class="w"> </span><span class="m">255</span>.255.255.0
network<span class="w"> </span><span class="m">192</span>.168.0.0
broadcast<span class="w"> </span><span class="m">192</span>.168.0.255
</code></pre></div>
<p>重启网络:</p>
<div class="highlight"><pre><span></span><code>/etc/init.d/networking<span class="w"> </span>restart
</code></pre></div>
<p>就将原先每次重启时,可能变化的动态 IP 变成内网的静态 IP 了</p>
<h3 id="connection-refused">Connection refused<a class="headerlink" href="#connection-refused" title="Permanent link">¶</a></h3>
<p>然后,配置了 <code>sudo</code> 用户,刷了初始口令,就可以离开 VGA 远程随时随地进行控制了!</p>
<p>可是竟然反馈说: <code>Connection refused</code></p>
<p>果断 Google 发布,是常见问题!</p>
<p><a href="http://askubuntu.com/questions/30080/how-to-solve-connection-refused-errors-in-ssh-connection">openssh - How to solve 'Connection refused' errors in SSH connection? - Ask Ubuntu</a></p>
<p>完全无法相信自个儿的眼睛! 竟然是因为根本没有 <code>sshd</code> 进程运行的原因!</p>
<div class="highlight"><pre><span></span><code>sudo<span class="w"> </span>apt-get<span class="w"> </span>install<span class="w"> </span>openssh-server<span class="w"> </span>openssh-client
sudo<span class="w"> </span>/etc/init.d/ssh<span class="w"> </span>start
</code></pre></div>
<p>再尝试</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>ssh<span class="w"> </span><span class="m">192</span>.168.0.111
</code></pre></div>
<p>一切正常了!</p>
<h3 id="ftab">ftab<a class="headerlink" href="#ftab" title="Permanent link">¶</a></h3>
<p>看CB3 的硬件参数,应该有8G 内置空间的, 但是查询:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>df<span class="w"> </span>-h
Filesystem<span class="w"> </span>Size<span class="w"> </span>Used<span class="w"> </span>Avail<span class="w"> </span>Use%<span class="w"> </span>Mounted<span class="w"> </span>on
/dev/root<span class="w"> </span><span class="m">2</span>.0G<span class="w"> </span>1019M<span class="w"> </span>907M<span class="w"> </span><span class="m">53</span>%<span class="w"> </span>/
devtmpfs<span class="w"> </span>913M<span class="w"> </span><span class="m">4</span>.0K<span class="w"> </span>913M<span class="w"> </span><span class="m">1</span>%<span class="w"> </span>/dev
none<span class="w"> </span><span class="m">4</span>.0K<span class="w"> </span><span class="m">0</span><span class="w"> </span><span class="m">4</span>.0K<span class="w"> </span><span class="m">0</span>%<span class="w"> </span>/sys/fs/cgroup
none<span class="w"> </span>183M<span class="w"> </span>160K<span class="w"> </span>183M<span class="w"> </span><span class="m">1</span>%<span class="w"> </span>/run
none<span class="w"> </span><span class="m">5</span>.0M<span class="w"> </span><span class="m">0</span><span class="w"> </span><span class="m">5</span>.0M<span class="w"> </span><span class="m">0</span>%<span class="w"> </span>/run/lock
none<span class="w"> </span>913M<span class="w"> </span><span class="m">0</span><span class="w"> </span>913M<span class="w"> </span><span class="m">0</span>%<span class="w"> </span>/run/shm
none<span class="w"> </span>100M<span class="w"> </span><span class="m">0</span><span class="w"> </span>100M<span class="w"> </span><span class="m">0</span>%<span class="w"> </span>/run/user
</code></pre></div>
<p>不对哪,肿么只有2G 的空间?</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>sudo<span class="w"> </span>fdisk<span class="w"> </span>-l
Disk<span class="w"> </span>/dev/nand:<span class="w"> </span><span class="m">7700</span><span class="w"> </span>MB,<span class="w"> </span><span class="m">7700742144</span><span class="w"> </span>bytes
<span class="m">255</span><span class="w"> </span>heads,<span class="w"> </span><span class="m">63</span><span class="w"> </span>sectors/track,<span class="w"> </span><span class="m">936</span><span class="w"> </span>cylinders,<span class="w"> </span>total<span class="w"> </span><span class="m">15040512</span><span class="w"> </span>sectors
<span class="nv">Units</span><span class="w"> </span><span class="o">=</span><span class="w"> </span>sectors<span class="w"> </span>of<span class="w"> </span><span class="m">1</span><span class="w"> </span>*<span class="w"> </span><span class="nv">512</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">512</span><span class="w"> </span>bytes
Sector<span class="w"> </span>size<span class="w"> </span><span class="o">(</span>logical/physical<span class="o">)</span>:<span class="w"> </span><span class="m">512</span><span class="w"> </span>bytes<span class="w"> </span>/<span class="w"> </span><span class="m">512</span><span class="w"> </span>bytes
I/O<span class="w"> </span>size<span class="w"> </span><span class="o">(</span>minimum/optimal<span class="o">)</span>:<span class="w"> </span><span class="m">512</span><span class="w"> </span>bytes<span class="w"> </span>/<span class="w"> </span><span class="m">512</span><span class="w"> </span>bytes
Disk<span class="w"> </span>identifier:<span class="w"> </span>0x00000000
Disk<span class="w"> </span>/dev/nand<span class="w"> </span>doesn<span class="s1">'t contain a valid partition table</span>
<span class="s1">Disk /dev/nanda: 67 MB, 67108864 bytes</span>
<span class="s1">255 heads, 63 sectors/track, 8 cylinders, total 131072 sectors</span>
<span class="s1">Units = sectors of 1 * 512 = 512 bytes</span>
<span class="s1">Sector size (logical/physical): 512 bytes / 512 bytes</span>
<span class="s1">I/O size (minimum/optimal): 512 bytes / 512 bytes</span>
<span class="s1">Disk identifier: 0x00000000</span>
<span class="s1"> Device Boot Start End Blocks Id System</span>
<span class="s1">Disk /dev/nandb: 2147 MB, 2147483648 bytes</span>
<span class="s1">255 heads, 63 sectors/track, 261 cylinders, total 4194304 sectors</span>
<span class="s1">Units = sectors of 1 * 512 = 512 bytes</span>
<span class="s1">Sector size (logical/physical): 512 bytes / 512 bytes</span>
<span class="s1">I/O size (minimum/optimal): 512 bytes / 512 bytes</span>
<span class="s1">Disk identifier: 0x00000000</span>
<span class="s1">Disk /dev/nandb doesn'</span>t<span class="w"> </span>contain<span class="w"> </span>a<span class="w"> </span>valid<span class="w"> </span>partition<span class="w"> </span>table
Disk<span class="w"> </span>/dev/nandc:<span class="w"> </span><span class="m">5469</span><span class="w"> </span>MB,<span class="w"> </span><span class="m">5469372416</span><span class="w"> </span>bytes
<span class="m">255</span><span class="w"> </span>heads,<span class="w"> </span><span class="m">63</span><span class="w"> </span>sectors/track,<span class="w"> </span><span class="m">664</span><span class="w"> </span>cylinders,<span class="w"> </span>total<span class="w"> </span><span class="m">10682368</span><span class="w"> </span>sectors
<span class="nv">Units</span><span class="w"> </span><span class="o">=</span><span class="w"> </span>sectors<span class="w"> </span>of<span class="w"> </span><span class="m">1</span><span class="w"> </span>*<span class="w"> </span><span class="nv">512</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">512</span><span class="w"> </span>bytes
Sector<span class="w"> </span>size<span class="w"> </span><span class="o">(</span>logical/physical<span class="o">)</span>:<span class="w"> </span><span class="m">512</span><span class="w"> </span>bytes<span class="w"> </span>/<span class="w"> </span><span class="m">512</span><span class="w"> </span>bytes
I/O<span class="w"> </span>size<span class="w"> </span><span class="o">(</span>minimum/optimal<span class="o">)</span>:<span class="w"> </span><span class="m">512</span><span class="w"> </span>bytes<span class="w"> </span>/<span class="w"> </span><span class="m">512</span><span class="w"> </span>bytes
Disk<span class="w"> </span>identifier:<span class="w"> </span>0x00000000
Disk<span class="w"> </span>/dev/nandc<span class="w"> </span>doesn<span class="err">'</span>t<span class="w"> </span>contain<span class="w"> </span>a<span class="w"> </span>valid<span class="w"> </span>partition<span class="w"> </span>table
</code></pre></div>
<p>果然有 <code>/dev/nandc</code> 没有挂上;</p>
<p>于是,先建立文件系统:</p>
<div class="highlight"><pre><span></span><code>mkfs.ext4 /dev/nandc
mke2fs 1.42.5 (29-Jul-2012)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
...
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks):
done
Writing superblocks and filesystem accounting information: done
</code></pre></div>
<p>然后,不折腾,直接使用: <code>/etc/rc.local</code></p>
<div class="highlight"><pre><span></span><code>sudo mount /dev/nandc /mnt/nandc
</code></pre></div>
<p>追加一行,完成! 这样重启时,将在最后一刻重新挂接上丢失的分区</p>
<h3 id="_6">其它<a class="headerlink" href="#_6" title="Permanent link">¶</a></h3>
<p>习惯性的安装 <code>htop</code> 一看:</p>
<p><img alt="ct_default_deamon.png(PNG 图像,1005x709 像素)" src="http://zoomq.qiniudn.com/ZHGDG/2014/140111-CBInstallfest.1/ct_default_deamon.png"/></p>
<p>目测, 这一镜像的程序猿是 <code>LAMP</code> 标准屌丝web 程序猿哪!!!</p>
<p>按惯例, <code>server</code> 版的发行系统镜像,应该是最小运维依赖核心系统:</p>
<ul>
<li>有最稳定的 内核</li>
<li>包含最常见的系统工具</li>
<li>包含最常见的硬件驱动</li>
<li>默认启动 <code>sshd</code></li>
<li>默认配置好 <code>apt-fast</code> ~ 用 axel 来加速 apt-get 软件安装</li>
<li>..etc. 总之是面向 SA 的一个方便环境</li>
</ul>
<p>怎么也没有想到,默认是启动跑了 <code>MySQL</code>+<code>Apache</code> 这两种一般 SA 一见就删除的东西</p>
<p>有点 <code>细思恐极</code> CB 应该及时提升自个儿 SA 的运营观念了,不能停留在上世纪了呢...</p>
<h1 id="todo">TODO<a class="headerlink" href="#todo" title="Permanent link">¶</a></h1>
<p>为了完全替代俺家原先的家庭服务器,可以支持多系统的内网络使用,
还要折腾的事儿有:</p>
<ol>
<li>通过 USB 挂接 FreeBSD 格式化的 UFS 分区</li>
<li>通过板载 SATA 接口,加装 2.5吋 1T 新硬盘</li>
<li>安装 Samba 系统,提供空间给其它 M$ 设备使用</li>
<li>安装 netatalk ,支持 <code>Apple Time Machine</code></li>
<li>安装 MLDonkey 通过网页控制 <code>P2P</code> 下载</li>
<li>安装 MiniDLNA 发布家庭媒体服务,支持远程播放下载的电影</li>
</ol>
<p>...</p>
<p>总之,要搾干 CB 的一切潜能!</p>
<h1 id="_7">参考:<a class="headerlink" href="#_7" title="Permanent link">¶</a></h1>
<p><a href="http://dyhr.com/2013/11/22/how-to-install-lubuntu-server-on-cubietruck-from-mac-os-x/">How to install Lubuntu Server on Cubietruck from Mac OS X</a></p>
<h2 id="cbuieboard">CbuieBoard<a class="headerlink" href="#cbuieboard" title="Permanent link">¶</a></h2>
<p><a href="http://www.ifanr.com/367898">Cubieboard :享誉国外 Linux 圈子的中国产品- 爱范儿· Beats of Bits</a>
- <a href="http://linux-sunxi.org/Cubieboard/zh_cn">Cubieboard/zh cn - linux-sunxi.org</a></p>
<ul>
<li><a href="http://cubieboard.org/2013/10/30/cubieboard3-cubietruck-is-all-ready/">Cubieboard3: Cubietruck is all ready</a> (cubieboard.org)</li>
<li><a href="http://docs.cubieboard.org/tutorials/cb3/start">Tutorials for Cubietruck</a> (cubieboard.org)</li>
<li><a href="http://docs.cubieboard.org/faq/faqs">FAQ</a> (cubieboard.org)</li>
</ul>
<h2 id="linux">Linux<a class="headerlink" href="#linux" title="Permanent link">¶</a></h2>
<ul>
<li><a href="http://docs.cubieboard.org/tutorials/common/livesuit_installation_guide">LiveSuit Guide</a> (cubieboard.org)</li>
<li><a href="http://www.lubuntu.net/">www.lubuntu.net</a></li>
<li><a href="https://help.ubuntu.com/community/InstallingANewHardDrive?action=fullsearch&value=linkto%3A%22InstallingANewHardDrive%22&context=180">InstallingANewHardDrive</a></li>
<li><a href="http://archlinuxarm.org/platforms/armv7/allwinner/cubieboard">Cubieboard | Arch Linux ARM</a></li>
<li><a href="http://archlinuxarm.org/platforms/armv7/allwinner/cubieboard-2">Cubieboard 2 | Arch Linux ARM</a></li>
</ul>
<h1 id="changelog">Changelog<a class="headerlink" href="#changelog" title="Permanent link">¶</a></h1>
<ul>
<li>140119 终于汇集了所有唠叨!</li>
<li>140111 开始总结</li>
</ul>PythonisT happy guido ;-)2014-01-07T00:00:00+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2014-01-07:/140106-pycon2013tee-guido.html<p>一切开始自2006年!</p>
<ul>
<li>起初ZEUUX 作TEE 只是为了好玩,而且 Gudio 很喜欢: 有照片为证<a href="http://wiki.woodpecker.org.cn/moin/ObpLovelyPython/LpyAttachZoomq#A.2BTrpyaQ-">ObpLovelyPython/LpyAttachZoomq - Woodpecker Wiki for CPUG</a></li>
<li>然后,就没有然后了...</li>
</ul>
<p>后来, 好容易一个蠎 …</p><p>一切开始自2006年!</p>
<ul>
<li>起初ZEUUX 作TEE 只是为了好玩,而且 Gudio 很喜欢: 有照片为证<a href="http://wiki.woodpecker.org.cn/moin/ObpLovelyPython/LpyAttachZoomq#A.2BTrpyaQ-">ObpLovelyPython/LpyAttachZoomq - Woodpecker Wiki for CPUG</a></li>
<li>然后,就没有然后了...</li>
</ul>
<p>后来, 好容易一个蠎年了! 为了蠎年的 PyCon2013China, 启动了</p>
<ul>
<li><a href="http://python-china.org/topic/544">蠎年蠎衫(PythonisT-shirt)设计大赛! — Python China</a></li>
<li>然后,也没有然后了...</li>
</ul>
<p>再然后,<a href="https://twitter.com/stephanie__yu/status/381862928598577152">Twitter / stephanie__yu: @gvanrossum http://t.co/WSAYnXhbt2</a></p>
<ul>
<li>我蠎女神搭讪 Gudio 成功</li>
<li>当年的蠎衫,老爹竟然一直在穿!</li>
<li>于是又火了四处求购的呼声!</li>
<li>然后,也没有然后了...</li>
</ul>
<p>最终, 金山赞助了PyCon2013China 珠海+北京场, 俺就果断使用了封藏的设计,给所有来参加的行者,送了件:</p>
<ul>
<li><a href="http://blog.zhgdg.org/2013-12/et16-pycon-zh/">PyCon2013China 珠海场小结</a></li>
<li>另外,精制了一小批, EMS 给了大会上特别分享了视频的海外 Pythonner<ul>
<li><a href="http://v.youku.com/v_show/id_XNjQ1OTMzODQw.html">HRYR:用Python搭建信号采集分析系统</a></li>
<li><a href="http://v.youku.com/v_show/id_XNjQ1OTM3MDk2.html">EKR:Leo</a></li>
</ul>
</li>
<li>当然有 Guido:<ul>
<li><a href="https://twitter.com/gvanrossum/status/420249260961968128">Twitter / gvanrossum: T shift from Chinese user group. ...</a></li>
</ul>
</li>
</ul>
<p><img alt="140107-guido-twitter.png(PNG 图像,558x580 像素)" src="http://zoomq.qiniudn.com/CPyUG/zoomquiet-design-collection/140107-guido-twitter.png"></p>
<p>以上,有关蠎衫的故事,就是这些,再过12年,又能发生什么?!</p>
<p><img alt="design-by zoomquiet " src="http://zoomq.qiniudn.com/CPyUG/zoomquiet-design-collection/favicon/140101-design-by.png"></p>from Lion jump into Mavericks2013-12-30T00:00:00+08:002015-04-09T15:23:50+08:00Zoom.Quiettag:blog.zoomquiet.io,2013-12-30:/jump-into-mavericks.html
<h1 id="_1">为毛<a class="headerlink" href="#_1" title="Permanent link">¶</a></h1>
<p>得承认是被 老池的文章忽悠到了,
而且, 10.9 免费了, 进一步的通过OS 提高了电池/内存的使用效率,
最关键的,在 <a href="http://techparty.org/events/2013/12/29/et-ecugcon-sz/">无责任 …</a></p>
<h1 id="_1">为毛<a class="headerlink" href="#_1" title="Permanent link">¶</a></h1>
<p>得承认是被 老池的文章忽悠到了,
而且, 10.9 免费了, 进一步的通过OS 提高了电池/内存的使用效率,
最关键的,在 <a href="http://techparty.org/events/2013/12/29/et-ecugcon-sz/">无责任报道~ECUG2013Con</a> 中提及过的,
有好基友,已经折腾过,明确从 10.7 直升没有问题!</p>
<p>于是一个月黑风高的晚上...</p>
<h1 id="_2">回顾<a class="headerlink" href="#_2" title="Permanent link">¶</a></h1>
<p>宏观上没有想象的复杂,因为真心作到了零配置!
几乎所有非第三方的配置,都继承了下来不用折腾!</p>
<p>唯三的折腾:</p>
<ol>
<li>Python 环境</li>
<li>Qt 环境</li>
<li>sshfs</li>
</ol>
<p>严正推荐:</p>
<p><a href="file:///Users/zoomq/mnt/%E5%BF%AB%E7%9B%98/zScrapBook/ZqFLOSS/data/20131230190257/index.html">Mavericksでbrew upgradeしたらハマった話</a></p>
<p>等等日文的相关纪要非常实在,直觉,顺序合理,值得,多参考.</p>
<h2 id="python-qt-for-leo">Python + Qt for Leo<a class="headerlink" href="#python-qt-for-leo" title="Permanent link">¶</a></h2>
<p>大家知道俺是 <a href="http://wiki.woodpecker.org.cn/moin/LiterateProgramming">文学化编程</a>
的拥趸,
所以,一直使用 <a href="http://wiki.woodpecker.org.cn/moin/LeoEnvironment">Leo</a>
作为主要编程环境的,</p>
<p>10.9 以后 Python 不内置安装了,
Qt 当然从来也没有内置过.
所以,</p>
<h3 id="python">Python<a class="headerlink" href="#python" title="Permanent link">¶</a></h3>
<p>当然,系统的用 <code>brew install python</code> 了,</p>
<p>而其它各种项目开发时,就要综合使用</p>
<h4 id="pyenvvirtualenv">Pyenv+VirtualEnv<a class="headerlink" href="#pyenvvirtualenv" title="Permanent link">¶</a></h4>
<p>Pyenv 是这样一种神器:</p>
<p>完全的面向shell
通过环境变量的自动配置
形成复合Python版本共存</p>
<p>VirtualEnv 有 Pyenv 的插件
所以,可以利用已安装好的环境,快速复制出项目专用的,
结果,引发了滥用,特别舒服的那种:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>pyenv<span class="w"> </span>versions
*<span class="w"> </span>system<span class="w"> </span><span class="o">(</span><span class="nb">set</span><span class="w"> </span>by<span class="w"> </span>/Users/zoomq/.pyenv/version<span class="o">)</span>
<span class="w"> </span><span class="m">2</span>.7.3
<span class="w"> </span><span class="m">2</span>.7.5
<span class="w"> </span><span class="m">2</span>.7.6
<span class="w"> </span>273SAE
<span class="w"> </span>275lbTC
<span class="w"> </span>275pelican
<span class="w"> </span>276SphinxOBP
<span class="w"> </span>276chaos
<span class="w"> </span>276uliweb
<span class="w"> </span><span class="m">3</span>.2
<span class="w"> </span><span class="m">3</span>.3.2
<span class="w"> </span>32IPy
<span class="w"> </span>ipynotebook
<span class="w"> </span>pypy-2.2.1
<span class="w"> </span>pypy221chaos
</code></pre></div>
<p>主要遇到的问题是:</p>
<div class="highlight"><pre><span></span><code><span class="o">==></span><span class="w"> </span><span class="n">Installing</span><span class="w"> </span><span class="n">python3</span>
<span class="o">==></span><span class="w"> </span><span class="n">Downloading</span><span class="w"> </span><span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">python</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">ftp</span><span class="o">/</span><span class="n">python</span><span class="o">/</span><span class="mf">3.3</span><span class="o">.</span><span class="mi">3</span><span class="o">/</span><span class="n">Python</span><span class="o">-</span><span class="mf">3.3</span><span class="o">.</span><span class="mf">3.</span><span class="n">tar</span><span class="o">.</span><span class="n">bz2</span>
<span class="c1">######################################################################## 100.0%</span>
<span class="o">==></span><span class="w"> </span><span class="o">./</span><span class="n">configure</span><span class="w"> </span><span class="o">--</span><span class="n">prefix</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">python3</span><span class="o">/</span><span class="mf">3.3</span><span class="o">.</span><span class="mi">3</span><span class="w"> </span><span class="o">--</span><span class="n">enable</span><span class="o">-</span><span class="n">ipv6</span><span class="w"> </span><span class="o">--</span><span class="n">datarootdir</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">python3</span><span class="o">/</span><span class="mf">3.3</span><span class="o">.</span><span class="mi">3</span><span class="o">/</span><span class="n">share</span><span class="w"> </span><span class="o">--</span><span class="n">datadir</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">lo</span>
<span class="o">==></span><span class="w"> </span><span class="n">make</span>
<span class="o">==></span><span class="w"> </span><span class="n">make</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">PYTHONAPPSDIR</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">python3</span><span class="o">/</span><span class="mf">3.3</span><span class="o">.</span><span class="mi">3</span>
<span class="o">==></span><span class="w"> </span><span class="n">make</span><span class="w"> </span><span class="n">frameworkinstallextras</span><span class="w"> </span><span class="n">PYTHONAPPSDIR</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">python3</span><span class="o">/</span><span class="mf">3.3</span><span class="o">.</span><span class="mi">3</span><span class="o">/</span><span class="n">share</span><span class="o">/</span><span class="n">python3</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
<span class="n">Error</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">sitecustomize</span><span class="p">;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="n">PYTHONVERBOSE</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">traceback</span><span class="p">:</span>
<span class="n">ValueError</span><span class="p">:</span><span class="w"> </span><span class="n">list</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">x</span><span class="p">):</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">list</span>
</code></pre></div>
<p>指定具体版本,尝试,直到可以顺利安装出可用的就好.</p>
<p>严正表扬一下 'Yamashita, Yuu`</p>
<ul>
<li><a href="https://github.com/yyuu/pyenv/issues/95#issuecomment-31392999">How to config pyenv's pip ? · Issue #95 · yyuu/pyenv</a></li>
<li>绝对认真的回答了俺的提问,虽然不了了之,但是,一个常用工具的作者,可以如此关注一个不是问题的问题,实在太勤勉了,必须学习!</li>
</ul>
<h3 id="qt-for-leo">Qt for Leo<a class="headerlink" href="#qt-for-leo" title="Permanent link">¶</a></h3>
<p>参考:</p>
<ul>
<li><a href="http://support.apple.com/kb/HT5293">About X11 and OS X</a></li>
<li><a href="http://xquartz.macosforge.org/landing/">XQuartz</a></li>
</ul>
<p>以及:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>brew<span class="w"> </span>install<span class="w"> </span><span class="nv">pyqt</span>
<span class="o">==</span>><span class="w"> </span>Downloading<span class="w"> </span>http://downloads.sf.net/project/pyqt/PyQt4/PyQt-4.10.3/PyQt-mac-gpl-4.10.3.tar.gz
Already<span class="w"> </span>downloaded:<span class="w"> </span>/Library/Caches/Homebrew/pyqt-4.10.3.tar.gz
<span class="o">==</span>><span class="w"> </span>Patching
patching<span class="w"> </span>file<span class="w"> </span>configure.py
<span class="o">==</span>><span class="w"> </span>/usr/local/opt/python/bin/python2<span class="w"> </span>configure.py<span class="w"> </span>--confirm-license<span class="w"> </span>--bindir<span class="o">=</span>/usr/local/Cellar/pyqt/4.10.3/bin<span class="w"> </span>--destdir<span class="o">=</span>/usr/local/Cellar/
Error:<span class="w"> </span>Unable<span class="w"> </span>to<span class="w"> </span>find<span class="w"> </span>the<span class="w"> </span>qmake<span class="w"> </span>configuration<span class="w"> </span>file
/usr/local/Cellar/qt/4.8.5/mkspecs/unsupported/macx-clang-libc++/qmake.conf.
Use<span class="w"> </span>the<span class="w"> </span>QMAKESPEC<span class="w"> </span>environment<span class="w"> </span>variable<span class="w"> </span>to<span class="w"> </span>specify<span class="w"> </span>the<span class="w"> </span>correct<span class="w"> </span>platform.
Determining<span class="w"> </span>the<span class="w"> </span>layout<span class="w"> </span>of<span class="w"> </span>your<span class="w"> </span>Qt<span class="w"> </span>installation...
READ<span class="w"> </span>THIS:<span class="w"> </span>https://github.com/Homebrew/homebrew/wiki/troubleshooting
</code></pre></div>
<p>多多 Google 吧,很标准的环境驱动, Qt 官方提供了的,</p>
<p>然后, Leo 只是一堆 Py 脚本下载下来,
修订一下别名指向就好:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># ~/.bashrc for running Leo</span>
<span class="nb">alias</span><span class="w"> </span><span class="nv">leolanch</span><span class="o">=</span><span class="s2">"python /opt/bin/leo/launchLeo.py >> /dev/null 2>&1 &"</span>
</code></pre></div>
<h2 id="sshfs">伟光大的 sshfs<a class="headerlink" href="#sshfs" title="Permanent link">¶</a></h2>
<div class="highlight"><pre><span></span><code><span class="o">$</span><span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">link</span><span class="w"> </span><span class="n">fuse4x</span>
<span class="n">Linking</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">fuse4x</span><span class="o">/</span><span class="mf">0.9</span><span class="o">.</span><span class="mf">2.</span><span class="o">..</span><span class="w"> </span><span class="n">Warning</span><span class="p">:</span><span class="w"> </span><span class="n">Could</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="n">link</span><span class="w"> </span><span class="n">fuse4x</span><span class="o">.</span><span class="w"> </span><span class="n">Unlinking</span><span class="o">...</span>
<span class="n">Error</span><span class="p">:</span><span class="w"> </span><span class="n">Could</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="n">symlink</span><span class="w"> </span><span class="n">file</span><span class="p">:</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">fuse4x</span><span class="o">/</span><span class="mf">0.9</span><span class="o">.</span><span class="mi">2</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">pkgconfig</span><span class="o">/</span><span class="n">fuse</span><span class="o">.</span><span class="n">pc</span>
<span class="n">Target</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">pkgconfig</span><span class="o">/</span><span class="n">fuse</span><span class="o">.</span><span class="n">pc</span><span class="w"> </span><span class="n">already</span><span class="w"> </span><span class="n">exists</span><span class="o">.</span><span class="w"> </span><span class="n">You</span><span class="w"> </span><span class="n">may</span><span class="w"> </span><span class="n">need</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">delete</span><span class="w"> </span><span class="n">it</span><span class="o">.</span>
<span class="n">To</span><span class="w"> </span><span class="n">force</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">link</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">overwrite</span><span class="w"> </span><span class="n">all</span><span class="w"> </span><span class="n">other</span><span class="w"> </span><span class="n">conflicting</span><span class="w"> </span><span class="n">files</span><span class="p">,</span><span class="w"> </span><span class="n">do</span><span class="p">:</span>
<span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">link</span><span class="w"> </span><span class="o">--</span><span class="n">overwrite</span><span class="w"> </span><span class="n">formula_name</span>
<span class="n">To</span><span class="w"> </span><span class="n">list</span><span class="w"> </span><span class="n">all</span><span class="w"> </span><span class="n">files</span><span class="w"> </span><span class="n">that</span><span class="w"> </span><span class="n">would</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">deleted</span><span class="p">:</span>
<span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">link</span><span class="w"> </span><span class="o">--</span><span class="n">overwrite</span><span class="w"> </span><span class="o">--</span><span class="n">dry</span><span class="o">-</span><span class="n">run</span><span class="w"> </span><span class="n">formula_name</span>
<span class="n">zoomq</span><span class="w"> </span><span class="err">@</span><span class="w"> </span><span class="n">MBP111216ZQ</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">lib</span>
<span class="o">$</span><span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">link</span><span class="w"> </span><span class="o">--</span><span class="n">overwrite</span><span class="w"> </span><span class="n">fuse4x</span>
<span class="n">Linking</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">fuse4x</span><span class="o">/</span><span class="mf">0.9</span><span class="o">.</span><span class="mf">2.</span><span class="o">..</span><span class="w"> </span><span class="mi">7</span><span class="w"> </span><span class="n">symlinks</span><span class="w"> </span><span class="n">created</span>
<span class="o">$</span><span class="w"> </span><span class="n">brew</span><span class="w"> </span><span class="n">install</span><span class="w"> </span><span class="n">osxfuse</span>
<span class="o">==></span><span class="w"> </span><span class="n">Downloading</span><span class="w"> </span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">downloads</span><span class="o">.</span><span class="n">sf</span><span class="o">.</span><span class="n">net</span><span class="o">/</span><span class="n">project</span><span class="o">/</span><span class="n">machomebrew</span><span class="o">/</span><span class="n">Bottles</span><span class="o">/</span><span class="n">osxfuse</span><span class="o">-</span><span class="mf">2.6</span><span class="o">.</span><span class="mf">2.</span><span class="n">mavericks</span><span class="o">.</span><span class="n">bottle</span><span class="o">.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
<span class="o">==></span><span class="w"> </span><span class="n">Pouring</span><span class="w"> </span><span class="n">osxfuse</span><span class="o">-</span><span class="mf">2.6</span><span class="o">.</span><span class="mf">2.</span><span class="n">mavericks</span><span class="o">.</span><span class="n">bottle</span><span class="o">.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
<span class="o">==></span><span class="w"> </span><span class="n">Caveats</span>
<span class="n">If</span><span class="w"> </span><span class="n">upgrading</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">previous</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">osxfuse</span><span class="p">,</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">previous</span><span class="w"> </span><span class="n">kernel</span><span class="w"> </span><span class="n">extension</span>
<span class="n">will</span><span class="w"> </span><span class="n">need</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">unloaded</span><span class="w"> </span><span class="n">before</span><span class="w"> </span><span class="n">installing</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">new</span><span class="w"> </span><span class="n">version</span><span class="o">.</span><span class="w"> </span><span class="n">First</span><span class="p">,</span><span class="w"> </span><span class="n">check</span><span class="w"> </span><span class="n">that</span>
<span class="n">no</span><span class="w"> </span><span class="n">FUSE</span><span class="o">-</span><span class="n">based</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">systems</span><span class="w"> </span><span class="n">are</span><span class="w"> </span><span class="n">running</span><span class="p">:</span>
<span class="w"> </span><span class="n">mount</span><span class="w"> </span><span class="o">-</span><span class="n">t</span><span class="w"> </span><span class="n">osxfusefs</span>
<span class="n">Unmount</span><span class="w"> </span><span class="n">all</span><span class="w"> </span><span class="n">FUSE</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">systems</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">then</span><span class="w"> </span><span class="n">unload</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">kernel</span><span class="w"> </span><span class="n">extension</span><span class="p">:</span>
<span class="w"> </span><span class="n">sudo</span><span class="w"> </span><span class="n">kextunload</span><span class="w"> </span><span class="o">-</span><span class="n">b</span><span class="w"> </span><span class="n">com</span><span class="o">.</span><span class="n">github</span><span class="o">.</span><span class="n">osxfuse</span><span class="o">.</span><span class="n">filesystems</span><span class="o">.</span><span class="n">osxfusefs</span>
<span class="n">The</span><span class="w"> </span><span class="n">new</span><span class="w"> </span><span class="n">osxfuse</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">system</span><span class="w"> </span><span class="n">bundle</span><span class="w"> </span><span class="n">needs</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">installed</span><span class="w"> </span><span class="n">by</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">root</span><span class="w"> </span><span class="n">user</span><span class="p">:</span>
<span class="w"> </span><span class="n">sudo</span><span class="w"> </span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">cp</span><span class="w"> </span><span class="o">-</span><span class="n">RfX</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">osxfuse</span><span class="o">/</span><span class="mf">2.6</span><span class="o">.</span><span class="mi">2</span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Filesystems</span><span class="o">/</span><span class="n">osxfusefs</span><span class="o">.</span><span class="n">fs</span><span class="w"> </span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Filesystems</span>
<span class="w"> </span><span class="n">sudo</span><span class="w"> </span><span class="n">chmod</span><span class="w"> </span><span class="o">+</span><span class="n">s</span><span class="w"> </span><span class="o">/</span><span class="n">Library</span><span class="o">/</span><span class="n">Filesystems</span><span class="o">/</span><span class="n">osxfusefs</span><span class="o">.</span><span class="n">fs</span><span class="o">/</span><span class="n">Support</span><span class="o">/</span><span class="n">load_osxfusefs</span>
<span class="o">==></span><span class="w"> </span><span class="n">Summary</span>
<span class="err">🍺</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">local</span><span class="o">/</span><span class="n">Cellar</span><span class="o">/</span><span class="n">osxfuse</span><span class="o">/</span><span class="mf">2.6</span><span class="o">.</span><span class="mi">2</span><span class="p">:</span><span class="w"> </span><span class="mi">84</span><span class="w"> </span><span class="n">files</span><span class="p">,</span><span class="w"> </span><span class="mf">5.0</span><span class="n">M</span>
</code></pre></div>
<p>具体哪个管用,俺也没整明白,
反正,怎么折腾,
都是可以正当加载上 <code>Plan</code> 的内核库,
然后就可以对家庭服务器的所有硬盘,远程加载为本地目录了..</p>
<h1 id="changelog">Changelog<a class="headerlink" href="#changelog" title="Permanent link">¶</a></h1>
<ul>
<li>140616 再次精简,算是发布</li>
<li>140505 快速简述完成</li>
<li>140110 起意,总结</li>
</ul>Python 101: Writing a cleanup script2013-11-23T00:00:00+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2013-11-23:/py101-cleanup-script.html<p><a href="http://freepythontips.wordpress.com/2014/01/23/python-101-writing-a-cleanup-script/">Python 101: Writing a cleanup script | Bite Sized Python Tips</a></p>
<p>So hi there guys! I hope you are fine. So what is in this post? Today we will be writing a cleanup script. The idea for this post came from Mike Driscol who recently wrote a very useful post about …</p><p><a href="http://freepythontips.wordpress.com/2014/01/23/python-101-writing-a-cleanup-script/">Python 101: Writing a cleanup script | Bite Sized Python Tips</a></p>
<p>So hi there guys! I hope you are fine. So what is in this post? Today we will be writing a cleanup script. The idea for this post came from Mike Driscol who recently wrote a very useful post about writing a cleanup script in python. So how is my post different from his post? In my post I will be using path.py. When I used path.py for the first time I just fell in love with it.</p>
<h2 id="installing-pathpy">Installing path.py:<a class="headerlink" href="#installing-pathpy" title="Permanent link">¶</a></h2>
<p>So there are several ways for installing path.py. Path.py may be installed using setuptools or distribute or pip:
easy_install path.py
The latest release is always updated to the Python Package Index. The source code is hosted on Github.</p>
<h2 id="finding-the-number-of-files-in-a-directory">Finding the number of files in a directory:<a class="headerlink" href="#finding-the-number-of-files-in-a-directory" title="Permanent link">¶</a></h2>
<p>So our first task is to find the number of files present in a directory. In this example we will not iterate over subdirectories instead we will just count the number of files present in the top level directory. This one is simple. Here is my solution:</p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">path</span> <span class="kn">import</span> <span class="n">path</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">path</span><span class="p">(</span><span class="n">DIRECTORY</span><span class="p">)</span>
<span class="c1">#Replace DIRECTORY with your required directory</span>
<span class="n">num_files</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">d</span><span class="o">.</span><span class="n">files</span><span class="p">())</span>
<span class="nb">print</span> <span class="n">num_files</span>
</code></pre></div>
<p>In this script we first of all imported the path module. Then we set the num_file variable to 0. This variable is going to keep count for the number of files in our directory. Then we call the path function with a directory name. Firthermore we iterate over the files present in the root of our directory and increment the num_files variable. Finally we print the value of num_files variable. Here is a litle bit modified version of this script which outputs the number of subdirectories present in the root of our directory.</p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">path</span> <span class="kn">import</span> <span class="n">path</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">path</span><span class="p">(</span><span class="n">DIRECTORY</span><span class="p">)</span>
<span class="c1">#Replace DIRECTORY with your required directory</span>
<span class="n">num_dirs</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">d</span><span class="o">.</span><span class="n">dirs</span><span class="p">())</span>
<span class="nb">print</span> <span class="n">num_dirs</span>
</code></pre></div>
<h2 id="finding-the-number-of-files-recursively-in-a-directory">Finding the number of files recursively in a directory:<a class="headerlink" href="#finding-the-number-of-files-recursively-in-a-directory" title="Permanent link">¶</a></h2>
<p>That was easy! Wasn't it? So now our work is to find the number of files recursively in a directory. In order to acomplish this task we are given the walk() method by path.py. This is the same as os.walk(). So lets write a simple script for recursively listing all files in a directory and its subdirectories in Python.</p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">path</span> <span class="kn">import</span> <span class="n">path</span>
<span class="n">file_count</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">dir_count</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">total</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">path</span><span class="p">(</span><span class="n">DIRECTORY</span><span class="p">)</span>
<span class="c1">#Replace DIRECTORY with your required directory</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">d</span><span class="o">.</span><span class="n">walk</span><span class="p">():</span>
<span class="k">if</span> <span class="n">i</span><span class="o">.</span><span class="n">isfile</span><span class="p">():</span>
<span class="n">file_count</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">elif</span> <span class="n">i</span><span class="o">.</span><span class="n">isdir</span><span class="p">():</span>
<span class="n">dir_count</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">pass</span>
<span class="n">total</span> <span class="o">+=</span> <span class="mi">1</span>
</code></pre></div>
<p>print "Total number of files == {0}".format(file_count)
print "Total number of directories == {0}".format(dir_count)
That was again very easy. Now what if we want to pretty print the directory names? I know there are some terminal one-liners but here we are talking about Python only. Lets see how we can achieve that.</p>
<div class="highlight"><pre><span></span><code><span class="n">files_loc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="err">{}</span>
<span class="n">file_count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span>
<span class="n">dir_count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span>
<span class="n">total</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span>
<span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">d</span><span class="p">.</span><span class="n">walk</span><span class="p">()</span><span class="err">:</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">i</span><span class="p">.</span><span class="n">isfile</span><span class="p">()</span><span class="err">:</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">i</span><span class="p">.</span><span class="n">dirname</span><span class="p">().</span><span class="n">basename</span><span class="p">()</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="nl">files_loc</span><span class="p">:</span>
<span class="w"> </span><span class="n">files_loc</span><span class="o">[</span><span class="n">i.dirname().basename()</span><span class="o">]</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">i</span><span class="p">.</span><span class="n">basename</span><span class="p">())</span>
<span class="w"> </span><span class="k">else</span><span class="err">:</span>
<span class="w"> </span><span class="n">files_loc</span><span class="o">[</span><span class="n">i.dirname().basename()</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="err">[]</span>
<span class="w"> </span><span class="n">files_loc</span><span class="o">[</span><span class="n">i.dirname().basename()</span><span class="o">]</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">i</span><span class="p">.</span><span class="n">basename</span><span class="p">())</span>
<span class="w"> </span><span class="n">file_count</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="n">elif</span><span class="w"> </span><span class="n">i</span><span class="p">.</span><span class="n">isdir</span><span class="p">()</span><span class="err">:</span>
<span class="w"> </span><span class="n">dir_count</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="k">else</span><span class="err">:</span>
<span class="w"> </span><span class="n">pass</span>
<span class="w"> </span><span class="n">total</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span>
<span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="nl">files_loc</span><span class="p">:</span>
<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="ss">"|---"</span><span class="o">+</span><span class="n">i</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">files_loc</span><span class="o">[</span><span class="n">i</span><span class="o">]</span><span class="err">:</span>
<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="ss">"| |"</span>
<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="ss">"| `---"</span><span class="o">+</span><span class="n">i</span>
<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="ss">"|"</span>
</code></pre></div>
<p>There is nothing fancy here. In this script we are just pretty printing a directory and the files it contains. Now lets continue.</p>
<h2 id="deleting-a-specific-file-from-a-directory">Deleting a specific file from a directory:<a class="headerlink" href="#deleting-a-specific-file-from-a-directory" title="Permanent link">¶</a></h2>
<p>So lets suppose we have a file called this_file_sucks.py. Now how do we delete it. Lets make this seranio more real by saying that we do not know in which directory it is placed. Its simple to solve this problem as well. Just go to the top level directory and execute this script:</p>
<p>from path import path
d = path(DIRECTORY)</p>
<h1 id="replace-directory-with-your-desired-directory">replace directory with your desired directory<a class="headerlink" href="#replace-directory-with-your-desired-directory" title="Permanent link">¶</a></h1>
<p>for i in d.walk():
if i.isfile():
if i.name == 'php.py':
i.remove()
In the above script I did not implement any logging and error handling. That is left as an exercise for the reader.</p>
<h2 id="deleting-files-based-on-their-extension">Deleting files based on their extension<a class="headerlink" href="#deleting-files-based-on-their-extension" title="Permanent link">¶</a></h2>
<p>Just suppose you want to remove all the '.pyc' files from the directory. How would you go about dealing with this problem. Here is a solution which I came up with in path.py.</p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">path</span> <span class="kn">import</span> <span class="n">path</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">path</span><span class="p">(</span><span class="n">DIRECTORY</span><span class="p">)</span>
<span class="n">files</span> <span class="o">=</span> <span class="n">d</span><span class="o">.</span><span class="n">walkfiles</span><span class="p">(</span><span class="s2">"*.pyc"</span><span class="p">)</span>
<span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">files</span><span class="p">:</span>
<span class="n">file</span><span class="o">.</span><span class="n">remove</span><span class="p">()</span>
<span class="nb">print</span> <span class="s2">"Removed </span><span class="si">{}</span><span class="s2"> file"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
<span class="n">This</span> <span class="n">will</span> <span class="n">also</span> <span class="nb">print</span> <span class="n">the</span> <span class="n">name</span> <span class="n">of</span> <span class="n">the</span> <span class="n">file</span> <span class="n">which</span> <span class="ow">is</span> <span class="n">deleted</span><span class="o">.</span>
</code></pre></div>
<h2 id="deleting-files-based-on-their-size">Deleting files based on their size:<a class="headerlink" href="#deleting-files-based-on-their-size" title="Permanent link">¶</a></h2>
<p>So another interesting scenario. What if we want to delete those files which exceed 5Mb size?</p>
<p><code>NOTE:</code> There is a difference between Mb and MB. I will be covering Mb here.
Is it possible with path.py? Yes it is! So here is a script which does this work:</p>
<div class="highlight"><pre><span></span><code>d = path('./')
del_size = 4522420
for i in d.walk():
if i.isfile():
if i.size > del_size:
#4522420 is approximately equal to 4.1Mb
#Change it to your desired size
i.remove()
</code></pre></div>
<p>So we saw how we can remove files based on their size.</p>
<h2 id="deleting-files-based-on-their-last-access-time">Deleting files based on their last access time<a class="headerlink" href="#deleting-files-based-on-their-last-access-time" title="Permanent link">¶</a></h2>
<p>In this part we will take a look on how to delete files based on their last access time. I have written the code below to achieve this target. Just change the number of days to anything you like. This script will remove the files which were last modified before the DAYS variable.</p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">path</span> <span class="kn">import</span> <span class="n">path</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="c1">#Change the DAYS to your liking</span>
<span class="n">DAYS</span> <span class="o">=</span> <span class="mi">6</span>
<span class="n">removed</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">path</span><span class="p">(</span><span class="n">DIRECTORY</span><span class="p">)</span>
<span class="c1">#Replace DIRECTORY with your required directory</span>
<span class="n">time_in_secs</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="p">(</span><span class="n">DAYS</span> <span class="o">*</span> <span class="mi">24</span> <span class="o">*</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">60</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">d</span><span class="o">.</span><span class="n">walk</span><span class="p">():</span>
<span class="k">if</span> <span class="n">i</span><span class="o">.</span><span class="n">isfile</span><span class="p">():</span>
<span class="k">if</span> <span class="n">i</span><span class="o">.</span><span class="n">mtime</span> <span class="o"><=</span> <span class="n">time_in_secs</span><span class="p">:</span>
<span class="n">i</span><span class="o">.</span><span class="n">remove</span><span class="p">()</span>
<span class="n">removed</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="nb">print</span> <span class="n">removed</span>
</code></pre></div>
<p>So we have also learned how to remove files based on their last modified time. If you want to delete files based on last access time just change i.mtime to i.atime and you will be good to go.</p>
<h2 id="goodbye">Goodbye<a class="headerlink" href="#goodbye" title="Permanent link">¶</a></h2>
<p>So that was it. I hope you liked the post. In the end I would like to make a public apology that my English is not good so you may find some grammar mistakes. You are requested to email them to me so that I can improve my English. If you liked this post then don't forget to follow me on twitter and facebook. A retweet won't hurt either! If you want to send me a pm then use this email.</p>
<h2 id="changelog">Changelog<a class="headerlink" href="#changelog" title="Permanent link">¶</a></h2>
<ul>
<li>140125 翻译 Weekly issue:99.5 时发现,转抄学习</li>
</ul>Letter to a young programmer2013-11-11T00:00:00+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2013-11-11:/guido-letter-2-young.html<p><img alt="guido" src="https://d262ilb51hltx0.cloudfront.net/max/700/1*2m0OBPBnBJu0WrobbfnBkg.png">
~ Guido van Rossum (inventor of Python)</p>
<h1 id="letter-to-a-young-programmer"><a href="http://neopythonic.blogspot.ca/2013/10/letter-to-young-programmer.html">Letter to a young programmer</a><a class="headerlink" href="#letter-to-a-young-programmer" title="Permanent link">¶</a></h1>
<p>Dear (insert name here),</p>
<p>I heard you enjoy a certain programming language named Python. Programming is a wonderful activity. I am a little jealous that you have access to computers at your age; when I grew up I didn't …</p><p><img alt="guido" src="https://d262ilb51hltx0.cloudfront.net/max/700/1*2m0OBPBnBJu0WrobbfnBkg.png">
~ Guido van Rossum (inventor of Python)</p>
<h1 id="letter-to-a-young-programmer"><a href="http://neopythonic.blogspot.ca/2013/10/letter-to-young-programmer.html">Letter to a young programmer</a><a class="headerlink" href="#letter-to-a-young-programmer" title="Permanent link">¶</a></h1>
<p>Dear (insert name here),</p>
<p>I heard you enjoy a certain programming language named Python. Programming is a wonderful activity. I am a little jealous that you have access to computers at your age; when I grew up I didn't even know what a computer was! I was an electronics hobbyist though, and my big dream was to build my own electronic calculator from discrete components. I never did do that, but I did build several digital clocks, and it was amazing to build something that complex and see it work. I hope you dream big too — programmers can make computers (and robots!) do amazing things, and this is a great time to become a programmer. Just imagine how much faster computers will be in five or ten years, and what you will be able to do with your skills then!</p>
<div class="highlight"><pre><span></span><code>—Guido van Rossum (inventor of Python)
THURSDAY, OCTOBER 24, 2013
</code></pre></div>
<p>从
<a href="http://us4.campaign-archive1.com/?u=9735795484d2e4c204da82a29&id=c8c36205c4">Pycoder's Weekly (Issue #89): Mavericks</a>
知道的 Guido 好萌信,`</p>
<blockquote>
<blockquote>
<blockquote>
<p>尝试翻译一下:</p>
</blockquote>
</blockquote>
</blockquote>
<div class="highlight"><pre><span></span><code><span class="err">亲</span><span class="o">:</span>
<span class="err">目测你正在享受一种叫</span><span class="n">Python</span><span class="w"> </span><span class="err">的编程语言</span><span class="o">.</span>
<span class="err">编程是种美妙的体验</span><span class="o">.</span>
<span class="err">俺很有点羡慕嫉妒恨你们</span><span class="w"> </span><span class="o">!</span><span class="err">在这个年龄就能接触电脑</span><span class="o">.</span>
<span class="err">俺那会儿子</span><span class="o">,</span><span class="err">甚至不知道什么是计算机</span><span class="o">!</span>
<span class="err">俺算一个电子爱好者</span><span class="o">,</span><span class="err">那时</span><span class="o">,</span><span class="err">最大的梦想是</span><span class="o">,</span><span class="err">亲手完成一个计算元件</span><span class="o">.</span>
<span class="err">俺从未作到这点</span><span class="o">.</span>
<span class="err">不过</span><span class="o">,</span><span class="err">倒是完成了几件数字时钟</span><span class="o">,</span>
<span class="err">每当见到如此复杂的东西</span><span class="o">,</span><span class="err">终于能工作时</span><span class="o">,</span><span class="err">哗</span><span class="o">!</span><span class="w"> </span><span class="err">那种感觉</span><span class="o">,,,</span>
<span class="err">俺期望你的梦想也足够大</span><span class="w"> </span><span class="err">—</span>
<span class="err">程序可以控制计算机</span><span class="o">(</span><span class="err">机械人</span><span class="o">)</span><span class="err">做出令人惊叹的事儿</span><span class="o">,</span>
<span class="err">这是个令程序员伟大的时代</span><span class="o">.</span>
<span class="err">现在就设想</span><span class="o">,</span><span class="mi">5</span><span class="err">到</span><span class="mi">10</span><span class="err">年后</span><span class="o">,</span><span class="err">能运用你的功能操作更快的计算机作到什么</span><span class="o">?!</span>
<span class="err">哗</span><span class="o">...</span>
</code></pre></div>
<h2 id="changelog">Changelog<a class="headerlink" href="#changelog" title="Permanent link">¶</a></h2>
<ul>
<li>140107 move into Pelican as zoomquiet.io</li>
<li>131027 pub. <a href="https://medium.com/i-m-h-o/e701a9dc714e">Letter to a young programmer — I. M. H. O. — Medium</a></li>
</ul>EKR to Chinese programmer2013-11-06T00:00:00+08:002019-09-08T12:14:36+08:00Zoom.Quiettag:blog.zoomquiet.io,2013-11-06:/ekr-selfintro-for-chinese.html<h1 id="leo">Leo 作者向中国开发者的自述<a class="headerlink" href="#leo" title="Permanent link">¶</a></h1>
<p><img alt="EKR" src="https://d262ilb51hltx0.cloudfront.net/max/700/1*yKVZtcJyfh-FHNEtXrqjPw.jpeg"></p>
<p><a href="http://leoeditor.com/">Leo</a> is OpenSource,written by Python,can run in M$/Linux/MAC/etc. ,Leo is Literate Environment Outline-oriented ;-)
EKR is her father.</p>
<p>BUT, what is "Literate" ,is hard to explained,
i try and try and try to show …</p><h1 id="leo">Leo 作者向中国开发者的自述<a class="headerlink" href="#leo" title="Permanent link">¶</a></h1>
<p><img alt="EKR" src="https://d262ilb51hltx0.cloudfront.net/max/700/1*yKVZtcJyfh-FHNEtXrqjPw.jpeg"></p>
<p><a href="http://leoeditor.com/">Leo</a> is OpenSource,written by Python,can run in M$/Linux/MAC/etc. ,Leo is Literate Environment Outline-oriented ;-)
EKR is her father.</p>
<p>BUT, what is "Literate" ,is hard to explained,
i try and try and try to show/share to Chinese People, BUT...
next week,there is another chance for try again, and ask EKR say some abt. self...
So! EKR writed down his colorful life!</p>
<p>I've been interested in computers from the time I was about 10 years old.</p>
<p>I studied mathematics at Michigan State University and computer science at the University of Wisconsin, Madison. There I meant my friend and mentor, D.R. (Bob) Fitzwater. Bob encouraged me to focus more on design, less on the "bits". He died several years ago—he would have enjoyed what has happened since.</p>
<p>When I first learned to program, my programs were "brittle": changing one part would break another. For several years I wanted to know how to solve this problem.</p>
<p>My first programming job was at IBM in Kingston New York. This was about 1974. I didn't like corporate culture. The problem was my own immaturity, not the people at IBM. Still, I'm happy I left.</p>
<p>While at IBM I studied the ideas of people like Edsjer Dijkstra and especially the great David L. Parnas. Parnas was writing before languages had classes. In fact, his ideas are the reason that Leo's classes have remained unchanged in concept even though they have been rewritten many times.</p>
<p>I left IBM after less than a year. For a while I owned a computer store in Madison Wisconsin, where I have lived ever since. The store didn't turn out too well... </p>
<p>I married Rebecca in 1980, and we have been a happy team ever since. Leo would not have been born without her. Rebecca and I have two children, James and Linda. James is 30, Linda 23.</p>
<p>About this time I started a computer business selling Sherlock, a tracing tool for C programs:
https://sourceforge.net/projects/leo/files/Miscellaneous/Sherlock/ </p>
<p>I received a patent for it, but the business went nowhere. Sherlock is not needed for tracing Python programs: the pattern used in Leo suffices.
The ideas behind Sherlock really ought to be part of Python's logging framework. Levels of logging are feeble compared to individually named and targeted logs.</p>
<p>I worked (from home) for about a year for a company called Tuple in Ballard, Washington. I wrote (in C) a very fast optimizing C compiler, assembler, linker and unix-like file system for them. See the CC2 stuff at:
https://sourceforge.net/projects/leo/files/Miscellaneous/CC2%20and%20Psyco/</p>
<p>This was before the days of unit tests! At that time, having the compiler compile itself was pretty much how testing was done!</p>
<p>I've been a fan of Donald Knuth ever since graduate school. I studied his books about TeX:</p>
<div class="highlight"><pre><span></span><code><span class="nv">Volume</span><span class="w"> </span><span class="nv">A</span>,<span class="w"> </span><span class="nv">The</span><span class="w"> </span><span class="nv">TeXbook</span><span class="w"> </span><span class="ss">(</span><span class="nv">Reading</span>,<span class="w"> </span><span class="nv">Massachusetts</span>:<span class="w"> </span><span class="nv">Addison</span><span class="o">-</span><span class="nv">Wesley</span>,<span class="w"> </span><span class="mi">1984</span><span class="ss">)</span>,<span class="w"> </span><span class="nv">x</span><span class="o">+</span><span class="mi">483</span><span class="nv">pp</span>.<span class="w"> </span>
<span class="nv">ISBN</span><span class="w"> </span><span class="mi">0</span><span class="o">-</span><span class="mi">201</span><span class="o">-</span><span class="mi">13447</span><span class="o">-</span><span class="mi">0</span>
<span class="nv">Volume</span><span class="w"> </span><span class="nv">B</span>,<span class="w"> </span><span class="nv">TeX</span>:<span class="w"> </span><span class="nv">The</span><span class="w"> </span><span class="nv">Program</span><span class="w"> </span><span class="ss">(</span><span class="nv">Reading</span>,<span class="w"> </span><span class="nv">Massachusetts</span>:<span class="w"> </span><span class="nv">Addison</span><span class="o">-</span><span class="nv">Wesley</span>,<span class="w"> </span><span class="mi">1986</span><span class="ss">)</span>,<span class="w"> </span><span class="nv">xviii</span><span class="o">+</span><span class="mi">600</span><span class="nv">pp</span>.<span class="w"> </span><span class="nv">ISBN</span><span class="w"> </span><span class="mi">0</span><span class="o">-</span><span class="mi">201</span><span class="o">-</span><span class="mi">13437</span><span class="o">-</span><span class="mi">3</span>
<span class="nv">Volume</span><span class="w"> </span><span class="nv">B</span><span class="w"> </span><span class="nv">is</span><span class="w"> </span><span class="nv">written</span><span class="w"> </span><span class="nv">in</span><span class="w"> </span><span class="nv">Pascal</span><span class="ss">(</span><span class="o">!</span><span class="ss">)</span><span class="w"> </span><span class="nv">and</span><span class="w"> </span><span class="nv">organized</span><span class="w"> </span><span class="ss">(</span><span class="k">if</span><span class="w"> </span><span class="nv">you</span><span class="w"> </span><span class="nv">can</span><span class="w"> </span><span class="k">call</span><span class="w"> </span><span class="nl">it</span><span class="w"> </span><span class="nv">that</span><span class="ss">)</span><span class="w"> </span><span class="nv">using</span><span class="w"> </span><span class="nv">Knuth</span><span class="err">'s WEB system. I studied WEB intensely.</span>
</code></pre></div>
<p>Despite understanding bits and pieces of the 600-page code in volume B, I really didn't understand the code. I asked myself, why is this so hard to understand? After perhaps 6 months of wondering, the basis of Leo came to me: webs are outlines in disguise. Actually, <em>all</em> programs are outlines in disguise.</p>
<p>You can read about the rest of Leo's history here:
http://leoeditor.com/appendices.html#history-of-leo</p>
<p>I learned about Python in 2001. I was working on the Python version of Leo on September 11.</p>
<p>Two years ago I got interested in Guido's keynote about static type checking. I contacted him and started this project:
https://groups.google.com/forum/#!forum/python-static-type-checking</p>
<p>I spent lots of time learning how to traverse parse trees quickly. That's not nothing, but it's only the beginning of the task. Perhaps next year I'll be able to do for type analysis what I did for traversing parse trees ;-)</p>
<p>
And that's about it. I've ever only been interested in programming. I love seeing how other people use Leo, but such excursions are not for me. I remain interested in programming because it has never been easy for me.</p>
<p>I am a mediocre wei chi player, despite many lessons from Yang Yi-Lun 杨以伦, pro 7 dan:
https://en.wikipedia.org/wiki/Yilun_Yang
I do know enough to appreciate famous games. </p>
<p>One of my favorites was played between the two great rivals Go Seigen 吳清源 and Kitani Minoru 木谷 実 on March 20, 1932.
Go Seigen won by resignation, despite losing about 25 stones.</p>
<p>I play the piano and take lessons from a great musician, Michael Butkus-Bomier: http://www.michaelbb.info/
I enjoy painting. About 20 years ago I received a black belt in karate.</p>
<p>HTH.</p>
<blockquote>
<blockquote>
<blockquote>
<p>试译如下:</p>
</blockquote>
</blockquote>
</blockquote>
<p>10岁开始,俺就对计算机上了心.</p>
<p>俺是密歇根州立大学数学系的,也是威斯康星大学麦迪逊学院计算机系的.在那儿,遇到了俺的导师(Bob) Fitzwater教授,他建议俺多关注设计,而不仅仅是"字节".
几年前,Bob 已仙去,不过,他要是知道俺在折腾什么一定会很高兴.</p>
<p>开始编程时,俺的程序特色是"脆":某处囧了,另外的也会杯具. 那些年俺一直在想法解决这种事儿!</p>
<p>俺第一份程序猿工作是在1974年进入 IBM (Kingston New York). 俺并不喜欢企业文化,当然问题在俺不在 IBM, 总之很高兴俺及时离开了.</p>
<p>有IBM 俺接触到象 Edsjer Dijkstra 或是 伟大的 David L. Parnas 们的想法.Parnas写的书面语言类, 诱发了 Leo 的类概念无论怎么重写都不会改变!</p>
<p>离开 IBM 快一年时.有一阵子,俺在威斯康星的麦迪逊那儿有个电脑店.事儿并不忙... </p>
<p>1980年,俺同 Rebecca 结婚了,从此有了俺自个儿的快乐团队.如果没有她, Leo 也诞生不出来. Rebecca 和俺有两个娃儿,James 和 Linda. 现在 James 30, Linda 23.</p>
<p>大约这时期,俺开始销售 Sherlock, 针对C程序的追踪工具.: https://sourceforge.net/projects/leo/files/Miscellaneous/Sherlock/
俺拥有相关专科,但是没什么业务.Sherlock 没必要对 Python 程序进行追踪: Leo 足够用了!
Sherlock背后的想法的确出自Python 的日志框架.分级的日志绝对比苍白的命名式日志要好用的多.</p>
<p>俺为华盛顿一家名为"Tuple in Ballard"的公司SOHO 了一年, 写(用C)了些很快的编译器,汇编器,链接器,以及 Unix样的文件系统.参考 CC2: https://sourceforge.net/projects/leo/files/Miscellaneous/CC2%20and%20Psyco/
这儿是几天前的集成测试结果!当时,编译过编译器自身比跑通测试重要的多.</p>
<p>毕业以来,俺一直是高纳德的粉丝. 学习过他有关TeX 的书.包括:</p>
<div class="highlight"><pre><span></span><code>卷A,TeXbook(阅读,马萨诸塞州:Addison-Wesley出版社,1984),X+483页. ISBN0-201-13447-0
卷B, TEX:程序(阅读,马萨诸塞州:Addison-Wesley出版社,1986),18+600页. ISBN0-201-13437-3
</code></pre></div>
<p>B卷是用 Pascal(!) 完成并组织的(甚至于可以调用它),运用了 高纳德的 WEB 系统.俺立即对 WEB 系统着迷了.</p>
<p>尽管对卷B 600多页中散布的代码进行了反复理解,依然一头雾水.俺反问自个儿,有这么难嘛?又过了大约半年, 完成了 Leo 的主要部分后,回过味儿来:</p>
<p>WEB 就是变形的大纲
事实上:</p>
<p>一切程序都是大纲的变形 !
Leo 其余的历史可以在这儿查阅:
http://leoeditor.com/appendices.html#history-of-leo</p>
<p>俺在2001 年才学的 Python.同年9月11日开始,就用Python 来构建 Leo 了.</p>
<p>两年前俺关注到 Guido 有关静态类型检查的报告.于是联系上他启动了这个项目:
https://groups.google.com/forum/#!forum/python-static-type-checking</p>
<p>俺花了大量的时间来学习如何快速遍历语法树.这不算什么事儿,但却是此任务的必然起点. 也许明年俺能基于语法树开展类型分析了 ;-)</p>
<p>(嚓! 王珢的 https://github.com/yinwang0/pysonar2 已经折腾很NB ;-)</p>
<p>是也乎,俺就是对编程感兴趣.俺喜欢见证大家对 Leo 的喜爱, 但是,这不会是俺的一切.俺保持编程的兴趣,因为对俺这从来不是简单的事儿.</p>
<p>俺是名普通的围棋爱好者, 从 Yang Yi-Lun (杨以伦)那儿学了很多, pro 7 dan: https://en.wikipedia.org/wiki/Yilun_Yang
俺能欣赏历史上知名的对弈, 其中最喜欢的是 1932年3月20号 吳清源 同 木谷 実(Kitani Minoru)的对战.尽管少了25颗棋子,但吳清源最终赢了!
俺也弹钢琴,并学习了伟大的 Michael Butkus-Bomier 的课程: http://www.michaelbb.info/
俺也享受绘画. 另外20年前,俺也拿到了空手道的黒带.</p>
<p>以上.</p>
<h2 id="changelog">Changelog<a class="headerlink" href="#changelog" title="Permanent link">¶</a></h2>
<ul>
<li>140107 move into Pelican as zoomquiet.io</li>
<li>131106 pub. <a href="https://medium.com/i-m-h-o/9520fee0b59f">EKR to Chinese programmer — I. M. H. O. — Medium</a></li>
</ul>