<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Python on Abel</title>
    <link>https://chen-huaneng.github.io/categories/python/</link>
    <description>Recent content in Python on Abel</description>
    <generator>Hugo</generator>
    <language>zh</language>
    <lastBuildDate>Sun, 23 Mar 2025 11:21:02 +0800</lastBuildDate>
    <atom:link href="https://chen-huaneng.github.io/categories/python/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>【Python】Gurobi求解器</title>
      <link>https://chen-huaneng.github.io/posts/2025/2025-03-23-gurobi/</link>
      <pubDate>Sun, 23 Mar 2025 11:21:02 +0800</pubDate>
      <guid>https://chen-huaneng.github.io/posts/2025/2025-03-23-gurobi/</guid>
      <description>&lt;h2 id=&#34;申请-gurobi-学术许可和安装-gurobi&#34;&gt;申请 &lt;code&gt;Gurobi&lt;/code&gt; 学术许可和安装 &lt;code&gt;Gurobi&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;申请 &lt;code&gt;Gurobi&lt;/code&gt; 学术许可和安装可以参考&lt;a href=&#34;https://zhuanlan.zhihu.com/p/24819586963&#34;
     
        target=&#34;_blank&#34; 
        rel=&#34;noopener nofollow noreferrer&#34; 
    &gt;
Gurobi最新安装与学术许可申请教程（2025） - 知乎&lt;/a&gt;或者官方的引导：&lt;a href=&#34;https://support.gurobi.com/hc/en-us/articles/14799677517585-Getting-Started-with-Gurobi-Optimizer&#34;
     
        target=&#34;_blank&#34; 
        rel=&#34;noopener nofollow noreferrer&#34; 
    &gt;
Getting Started with Gurobi Optimizer – Gurobi Help Center&lt;/a&gt;&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="申请-gurobi-学术许可和安装-gurobi">申请 <code>Gurobi</code> 学术许可和安装 <code>Gurobi</code></h2>
<p>申请 <code>Gurobi</code> 学术许可和安装可以参考<a href="https://zhuanlan.zhihu.com/p/24819586963"
     
        target="_blank" 
        rel="noopener nofollow noreferrer" 
    >
Gurobi最新安装与学术许可申请教程（2025） - 知乎</a>或者官方的引导：<a href="https://support.gurobi.com/hc/en-us/articles/14799677517585-Getting-Started-with-Gurobi-Optimizer"
     
        target="_blank" 
        rel="noopener nofollow noreferrer" 
    >
Getting Started with Gurobi Optimizer – Gurobi Help Center</a></p>
<h2 id="配置-python-环境">配置 <code>Python</code> 环境</h2>
<p>首先打开命令行终端，用 <code>Conda</code> 或者 <code>Miniconda</code> 单独创建一个环境：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">conda</span> <span class="n">create</span> <span class="n">-n</span> <span class="n">name_env</span>
</span></span></code></pre></div><p>如果因为 <code>Conda</code> 的启动环境导致 <code>pwsh</code> 启动缓慢，可以参考：<a href="https://github.com/conda/conda/issues/11648#issuecomment-3609884824"
     
        target="_blank" 
        rel="noopener nofollow noreferrer" 
    >
conda init powershell slows shell startup immensely. · Issue #11648 · conda/conda</a> 的方案来解决该问题。</p>
<p>激活环境：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">conda</span> <span class="n">activate</span> <span class="n">name_env</span>
</span></span></code></pre></div><p>用 <code>Conda</code> 包管理安装 <code>Gurobi</code> 到 <code>Python</code> 库中<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">conda</span> <span class="n">install</span> <span class="n">-c</span> <span class="n">gurobi</span> <span class="n">gurobi</span>
</span></span></code></pre></div><p>安装完之后，可以用下面的例子测试 <code>Gurobi</code> 是否能够正常使用：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">gurobipy</span> <span class="k">as</span> <span class="nn">gp</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">from</span> <span class="nn">gurobipy</span> <span class="kn">import</span> <span class="n">GRB</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">def</span> <span class="nf">test_gurobi</span><span class="p">():</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="c1"># 创建一个新的模型</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="n">model</span> <span class="o">=</span> <span class="n">gp</span><span class="o">.</span><span class="n">Model</span><span class="p">(</span><span class="s2">&#34;test_model&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="c1"># 添加变量</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="n">x</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">addVar</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">&#34;x&#34;</span><span class="p">,</span> <span class="n">vtype</span><span class="o">=</span><span class="n">GRB</span><span class="o">.</span><span class="n">CONTINUOUS</span><span class="p">,</span> <span class="n">lb</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="n">y</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">addVar</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">&#34;y&#34;</span><span class="p">,</span> <span class="n">vtype</span><span class="o">=</span><span class="n">GRB</span><span class="o">.</span><span class="n">CONTINUOUS</span><span class="p">,</span> <span class="n">lb</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="c1"># 更新模型以整合新变量</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="n">model</span><span class="o">.</span><span class="n">update</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="c1"># 设置目标函数：最大化 3x + 2y</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">        <span class="n">model</span><span class="o">.</span><span class="n">setObjective</span><span class="p">(</span><span class="mi">3</span> <span class="o">*</span> <span class="n">x</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">y</span><span class="p">,</span> <span class="n">GRB</span><span class="o">.</span><span class="n">MAXIMIZE</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="c1"># 添加约束条件</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">        <span class="c1"># x + y &lt;= 4</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">        <span class="n">model</span><span class="o">.</span><span class="n">addConstr</span><span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="n">y</span> <span class="o">&lt;=</span> <span class="mi">4</span><span class="p">,</span> <span class="s2">&#34;c0&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">
</span></span><span class="line"><span class="ln">23</span><span class="cl">        <span class="c1"># x &lt;= 2</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">        <span class="n">model</span><span class="o">.</span><span class="n">addConstr</span><span class="p">(</span><span class="n">x</span> <span class="o">&lt;=</span> <span class="mi">2</span><span class="p">,</span> <span class="s2">&#34;c1&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">
</span></span><span class="line"><span class="ln">26</span><span class="cl">        <span class="c1"># y &lt;= 3</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">        <span class="n">model</span><span class="o">.</span><span class="n">addConstr</span><span class="p">(</span><span class="n">y</span> <span class="o">&lt;=</span> <span class="mi">3</span><span class="p">,</span> <span class="s2">&#34;c2&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="c1"># 优化模型</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">        <span class="n">model</span><span class="o">.</span><span class="n">optimize</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">
</span></span><span class="line"><span class="ln">32</span><span class="cl">        <span class="c1"># 检查优化状态</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">        <span class="k">if</span> <span class="n">model</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="n">GRB</span><span class="o">.</span><span class="n">OPTIMAL</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;最优目标值: </span><span class="si">{</span><span class="n">model</span><span class="o">.</span><span class="n">ObjVal</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;x = </span><span class="si">{</span><span class="n">x</span><span class="o">.</span><span class="n">x</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;y = </span><span class="si">{</span><span class="n">y</span><span class="o">.</span><span class="n">x</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;没有找到最优解。&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">    
</span></span><span class="line"><span class="ln">40</span><span class="cl">    <span class="k">except</span> <span class="n">gp</span><span class="o">.</span><span class="n">GurobiError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Gurobi错误: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">    
</span></span><span class="line"><span class="ln">43</span><span class="cl">    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">44</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;其他错误: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl">
</span></span><span class="line"><span class="ln">46</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">47</span><span class="cl">    <span class="n">test_gurobi</span><span class="p">()</span>
</span></span></code></pre></div><p>如果能够正常使用会输出以下结果：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="ln"> 1</span><span class="cl">Optimize a model with 3 rows, 2 columns and 4 nonzeros
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">Model fingerprint: 0x5c2931af
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">Coefficient statistics:
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  Matrix range     [1e+00, 1e+00]
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">  Objective range  [2e+00, 3e+00]
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  Bounds range     [0e+00, 0e+00]
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  RHS range        [2e+00, 4e+00]
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">Presolve removed 2 rows and 0 columns
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">Presolve time: 0.00s
</span></span><span class="line"><span class="ln">10</span><span class="cl">Presolved: 1 rows, 2 columns, 2 nonzeros
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">Iteration    Objective       Primal Inf.    Dual Inf.      Time
</span></span><span class="line"><span class="ln">13</span><span class="cl">       0    1.2000000e+01   2.000000e+00   0.000000e+00      0s
</span></span><span class="line"><span class="ln">14</span><span class="cl">       1    1.0000000e+01   0.000000e+00   0.000000e+00      0s
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl">Solved in 1 iterations and 0.00 seconds (0.00 work units)
</span></span><span class="line"><span class="ln">17</span><span class="cl">Optimal objective  1.000000000e+01
</span></span><span class="line"><span class="ln">18</span><span class="cl">最优目标值: 10.0
</span></span><span class="line"><span class="ln">19</span><span class="cl">x = 2.0
</span></span><span class="line"><span class="ln">20</span><span class="cl">y = 2.0
</span></span></code></pre></div><div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://support.gurobi.com/hc/en-us/articles/360044290292-How-do-I-install-Gurobi-for-Python"
     
        target="_blank" 
        rel="noopener nofollow noreferrer" 
    >
How do I install Gurobi for Python? – Gurobi Help Center</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>【Python】Python Tkinter</title>
      <link>https://chen-huaneng.github.io/posts/2024/2024-03-29-python-tkinter/</link>
      <pubDate>Fri, 29 Mar 2024 17:31:24 +0800</pubDate>
      <guid>https://chen-huaneng.github.io/posts/2024/2024-03-29-python-tkinter/</guid>
      <description>&lt;h2 id=&#34;环境准备&#34;&gt;环境准备&lt;/h2&gt;
&lt;p&gt;建议在开始尝试 Tkinter 的时候先创建一个虚拟环境进行测试，首先先用 Conda 创建一个虚拟环境：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conda&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;create&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-name&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;of&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;your&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;environment&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;python&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;3.8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;其中 &lt;code&gt;python=3.8&lt;/code&gt; 是可选项，也可以指定下载其他的 Python 版本。&lt;/p&gt;
&lt;p&gt;然后激活环境：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conda&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;activate&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;of&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;your&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;environment&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;安装 Pip ，因为有些包不能通过 Conda 安装，而这个时候就需要使用 Pip，这里要注意一个点，要首先激活 Conda 的环境，然后在激活的虚拟环境中再通过 Conda 重新下载一个 Pip&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;，否则这时的虚拟环境中是不存在 Pip 的，所以如果直接执行 Pip 的命令会对原本的环境生效。&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="环境准备">环境准备</h2>
<p>建议在开始尝试 Tkinter 的时候先创建一个虚拟环境进行测试，首先先用 Conda 创建一个虚拟环境：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">conda</span> <span class="n">create</span> <span class="p">-</span><span class="n">-name</span> <span class="p">&lt;</span><span class="n">name</span> <span class="n">of</span> <span class="n">your</span> <span class="n">environment</span><span class="p">&gt;</span> <span class="n">python</span><span class="p">=</span><span class="mf">3.8</span>
</span></span></code></pre></div><p>其中 <code>python=3.8</code> 是可选项，也可以指定下载其他的 Python 版本。</p>
<p>然后激活环境：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">conda</span> <span class="n">activate</span> <span class="p">&lt;</span><span class="n">name</span> <span class="n">of</span> <span class="n">your</span> <span class="n">environment</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>安装 Pip ，因为有些包不能通过 Conda 安装，而这个时候就需要使用 Pip，这里要注意一个点，要首先激活 Conda 的环境，然后在激活的虚拟环境中再通过 Conda 重新下载一个 Pip<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>，否则这时的虚拟环境中是不存在 Pip 的，所以如果直接执行 Pip 的命令会对原本的环境生效。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">conda</span> <span class="n">install</span> <span class="n">pip</span>
</span></span></code></pre></div><p>这个时候通过查看 Conda 和 Pip 的环境可以查看是不是在虚拟环境中：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">conda</span> <span class="n">list</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="n">pip</span> <span class="n">list</span>
</span></span></code></pre></div><p>如果结果和原本环境中的输出是不一样的，那么就是成功创建虚拟环境并且激活虚拟环境了。</p>
<h2 id="tkinter-是什么">Tkinter 是什么<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></h2>
<p><code>tkinter</code>  是 <code>Python</code> 标准的GUI库，可以使用这个库快速地创建GUI应用。</p>
<h2 id="如何将-python-文件编译成-exe-文件">如何将 <code>Python</code> 文件编译成 <code>.exe</code> 文件<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></h2>
<ol>
<li>
<p>安装编译工具 <code>pyinstaller</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="ln">1</span><span class="cl">pip install pyinstaller
</span></span></code></pre></div></li>
<li>
<p>在文件路径下执行编译命令，其中 <code>-w</code> 参数是为了使得 <code>dos</code> 窗口不会随着 <code>tkinter</code> 窗口出现</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="ln">1</span><span class="cl">pyinstaller -F -w demo.py #demo.py是待编译的代码文件名
</span></span></code></pre></div></li>
<li>
<p>编译完成后一般会在当前文件夹中生成一个 <code>dist</code> 的文件夹，一个 <code>build</code> 文件夹和 一个 <code>demo.spec</code> 文件，编译后的 <code>.exe</code> 文件就在 <code>dist</code> 文件夹中。</p>
</li>
</ol>
<h3 id="编译后-exe-文件太大的问题">编译后 <code>.exe</code> 文件太大的问题</h3>
<p>原因是在编译时会把 <code>Python</code> 环境及库一起打包到 <code>.exe</code> 文件中，如果当前的 <code>Python</code> 环境中安装了很多的包，那么就会把所有的库带上，导致编译后的 <code>.exe</code> 文件过大。</p>
<p>因此解决方案就是为该文件单独创建相应的 <code>Python</code> 虚拟环境，只安装要编译 <code>Python</code> 文件所依赖的库。具体步骤如下：</p>
<ol>
<li>
<p>安装 <code>virtualenv</code> 用于创建虚拟环境</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="ln">1</span><span class="cl">pip install virtualenv
</span></span></code></pre></div></li>
<li>
<p>创建一个虚拟环境，建议将这个虚拟环境放在需要打包的 <code>Python</code> 文件夹中，便于后面的处理</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="ln">1</span><span class="cl">virtualenv py3exe_env #自定义命名虚拟环境的名称，这里是py3exe_env
</span></span></code></pre></div></li>
<li>
<p>创建完成之后进入到该目录</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">cd</span> py3exe_env/Script
</span></span></code></pre></div></li>
<li>
<p>在该目录下找到 <code>activate.ps1</code> 并执行</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="ln">1</span><span class="cl">activate.ps1
</span></span></code></pre></div></li>
<li>
<p>然后在该虚拟环境下安装要编译的文件需要依赖的 <code>Python</code> 库，当然也要重新安装 <code>pyinstaller</code>。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="ln">1</span><span class="cl">pip install pyinstaller
</span></span><span class="line"><span class="ln">2</span><span class="cl">pip install conda #比如这里安装conda
</span></span></code></pre></div></li>
<li>
<p>然后在该虚拟环境中回到要编译的文件目录下输入编译命令：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="ln">1</span><span class="cl">pyinstaller -F -w test.py #运行时不出现dos命令窗口
</span></span></code></pre></div></li>
</ol>
<h3 id="如何给-tkinter-添加自定义图标">如何给 Tkinter 添加自定义图标</h3>
<p>首先将要设置为图标的图片转换成 <code>.ico</code> 的格式，很多在线网站都能实现<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>。然后在运行 pyinstaller 之前给它加上一个参数<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="ln">1</span><span class="cl">pyinstaller -F -w --icon<span class="o">=</span>&lt;file name&gt;.ico test.py <span class="c1">#运行时不出现dos命令窗口</span>
</span></span></code></pre></div><p>比如你的 <code>.ico</code> 文件是 <code>icon.ico</code> 那么完整命令应该是：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="ln">1</span><span class="cl">pyinstaller -F -w --icon<span class="o">=</span>icon.ico test.py <span class="c1">#运行时不出现dos命令窗口</span>
</span></span></code></pre></div><p>还有一种方法是利用 Tkinter 的方法<sup id="fnref:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">tkinter</span> <span class="k">as</span> <span class="nn">tk</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># 创建主窗口</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="n">window</span> <span class="o">=</span> <span class="n">tk</span><span class="o">.</span><span class="n">Tk</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="n">window</span><span class="o">.</span><span class="n">title</span><span class="p">(</span><span class="s2">&#34;我的应用程序&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"># 设置图标</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="n">window</span><span class="o">.</span><span class="n">iconbitmap</span><span class="p">(</span><span class="s2">&#34;icon.ico&#34;</span><span class="p">)</span> <span class="c1"># 把 icon.ico 文件名改成你的文件名</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># 修改任务栏图标</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="n">window</span><span class="o">.</span><span class="n">wm_iconbitmap</span><span class="p">(</span><span class="s2">&#34;icon.ico&#34;</span><span class="p">)</span> <span class="c1"># 这里也要改</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="n">window</span><span class="o">.</span><span class="n">mainloop</span><span class="p">()</span>
</span></span></code></pre></div><p>还有一种方法是将图标硬编码进代码中<sup id="fnref:7"><a href="#fn:7" class="footnote-ref" role="doc-noteref">7</a></sup>，首先获取图标的二进制数据：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="kn">import</span> <span class="nn">base64</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s1">&#39;icon.ico&#39;</span><span class="p">,</span> <span class="s1">&#39;rb&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">open_icon</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">    <span class="n">b64str</span> <span class="o">=</span> <span class="n">base64</span><span class="o">.</span><span class="n">b64encode</span><span class="p">(</span><span class="n">open_icon</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">b64str</span><span class="p">)</span>
</span></span></code></pre></div><p>输出的字符串即为图标文件的二进制数据。假设输出为<code>b'abcdefg'</code>。然后利用获取的二进制数据，可以写出代码：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">tkinter</span> <span class="k">as</span> <span class="nn">tk</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">from</span> <span class="nn">PIL</span> <span class="kn">import</span> <span class="n">ImageTk</span>		<span class="c1"># pip install --upgrade Pillow</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kn">from</span> <span class="nn">base64</span> <span class="kn">import</span> <span class="n">b64decode</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="n">window</span> <span class="o">=</span> <span class="n">tk</span><span class="o">.</span><span class="n">Tk</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="n">window</span><span class="o">.</span><span class="n">title</span><span class="p">(</span><span class="s1">&#39;My Window&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="n">window</span><span class="o">.</span><span class="n">geometry</span><span class="p">(</span><span class="s1">&#39;500x300&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># window.iconbitmap(&#39;icon.ico&#39;)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="n">icon_img</span> <span class="o">=</span> <span class="sa">b</span><span class="s1">&#39;abcdefg&#39;</span>   <span class="c1"># 这里替换成你自己图标文件的二进制数据</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="n">icon_img</span> <span class="o">=</span> <span class="n">b64decode</span><span class="p">(</span><span class="n">icon_img</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="n">icon_img</span> <span class="o">=</span> <span class="n">ImageTk</span><span class="o">.</span><span class="n">PhotoImage</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="n">icon_img</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="n">window</span><span class="o">.</span><span class="n">tk</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="s1">&#39;wm&#39;</span><span class="p">,</span> <span class="s1">&#39;iconphoto&#39;</span><span class="p">,</span> <span class="n">window</span><span class="o">.</span><span class="n">_w</span><span class="p">,</span> <span class="n">icon_img</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="n">window</span><span class="o">.</span><span class="n">mainloop</span><span class="p">()</span>
</span></span></code></pre></div><p>这里注意一个点，PIL 已经不再维护了，所以需要 <code>pip install Pillow</code>，接口的代码是一样的。</p>
<h2 id="tkinter-快速入门">Tkinter 快速入门</h2>
<ul>
<li><a href="https://zhuanlan.zhihu.com/p/75872830"
     
        target="_blank" 
        rel="noopener nofollow noreferrer" 
    >
Tkinter简明教程 - 知乎 (zhihu.com)</a></li>
<li><a href="https://tkcalendar.readthedocs.io/en/stable/Calendar.html#"
     
        target="_blank" 
        rel="noopener nofollow noreferrer" 
    >
Calendar — tkcalendar 1.5.0 documentation</a> - 和显示日历相关的包</li>
</ul>
<h2 id="tkinter-实战">Tkinter 实战</h2>
<p>用 Tkinter 实现了一个博客管理器，主要用于管理我自己的博客文章，源代码和程序仓库<a href="https://github.com/chen-huaneng/BlogManager"
     
        target="_blank" 
        rel="noopener nofollow noreferrer" 
    >
请点我</a>。</p>
<p><div class="post-img-view">
  <a data-fancybox="gallery" href="/posts/2024/2024-03-29-python-tkinter/banner.png">
    <picture><source type="image/webp" srcset="/posts/2024/2024-03-29-python-tkinter/banner_hu_f3f1ad26d7fa2204.webp"><img loading="lazy" src="/posts/2024/2024-03-29-python-tkinter/banner.png">
    </picture>
  </a>
</div></p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://pythonjishu.com/sqsvggluonzijtk/"
     
        target="_blank" 
        rel="noopener nofollow noreferrer" 
    >
conda虚拟环境使用pip下载包到当前环境的两种方法 - Python技术站 (pythonjishu.com)</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://blog.csdn.net/weixin_47920722/article/details/128546996"
     
        target="_blank" 
        rel="noopener nofollow noreferrer" 
    >
【python】tkinter程序打包成exe可执行文件 全流程记录（windows系统）_tkinter打包exe-CSDN博客</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p><a href="https://docs.python.org/zh-cn/3/library/tk.html"
     
        target="_blank" 
        rel="noopener nofollow noreferrer" 
    >
Tk图形用户界面(GUI) — Python 3.12.2 文档</a>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p><a href="https://www.freeconvert.com/zh"
     
        target="_blank" 
        rel="noopener nofollow noreferrer" 
    >
文件转换器 - FreeConvert.com</a>&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p><a href="https://docs.pingcode.com/baike/1258257"
     
        target="_blank" 
        rel="noopener nofollow noreferrer" 
    >
如何给python生成的exe程序换图标 | PingCode智库</a>&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:6">
<p><a href="https://deepinout.com/tkinter/tkinter-questions/306_tkinter_changing_the_application_and_taskbar_icon_pythontkinter.html"
     
        target="_blank" 
        rel="noopener nofollow noreferrer" 
    >
Tkinter 修改应用程序和任务栏图标 – Python/Tkinter|极客笔记 (deepinout.com)</a>&#160;<a href="#fnref:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:7">
<p><a href="https://blog.csdn.net/Pragmatism_3568/article/details/105625881"
     
        target="_blank" 
        rel="noopener nofollow noreferrer" 
    >
硬编码tkinter的图标而不依赖于外部文件（不生成临时图标文件！）_python tinker logo可以不依赖外部文件吗-CSDN博客</a>&#160;<a href="#fnref:7" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
  </channel>
</rss>
