<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: codemee</title>
    <description>The latest articles on DEV Community by codemee (@codemee).</description>
    <link>https://dev.to/codemee</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F415015%2F26dc8621-f8da-4946-a902-17486b64662c.png</url>
      <title>DEV Community: codemee</title>
      <link>https://dev.to/codemee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/codemee"/>
    <language>en</language>
    <item>
      <title>Gemini 模型的 tokenizer</title>
      <dc:creator>codemee</dc:creator>
      <pubDate>Tue, 27 Jan 2026 02:52:19 +0000</pubDate>
      <link>https://dev.to/codemee/gemini-mo-xing-de-tokenizer-4bo0</link>
      <guid>https://dev.to/codemee/gemini-mo-xing-de-tokenizer-4bo0</guid>
      <description>&lt;p&gt;Gemini 並沒有提供類似 OpenAI 的 Tokenizer 頁面，方便大家觀察切割 token 的結果，如果你有使用 Vertex AI，則可以透過本文介紹的兩種方式查看。&lt;/p&gt;

&lt;h2&gt;
  
  
  Vertex AI Studio
&lt;/h2&gt;

&lt;p&gt;在 Vertex AI Studio 中，在輸入框輸入內容時，輸入框下緣會顯示目前的 token 數（Gemini 稱為『詞元』），像是底下的例子就告訴我們『這是什麼奇怪的世界？』會被切割為 5 個詞元：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmy48ql8pwvmho0cngl97.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmy48ql8pwvmho0cngl97.png" alt=" " width="800" height="237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;如果想知道實際切割的結果，只要按一下顯示詞元數量的地方，就會在右側顯示詳細資料：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj5bj0pa5subp9uvo6bct.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj5bj0pa5subp9uvo6bct.png" alt=" " width="700" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;它會以不同的背景色來標示每一個詞元的涵蓋範圍，你也可以切換頁次，觀察每個詞元對應的編號：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F48q4sr2lu1papwuor8yi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F48q4sr2lu1papwuor8yi.png" alt=" " width="700" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;要特別提醒你的是，Vertex AI Studio 和 Google AI Studio 雖然很相似，但這個觀察 token 切割結果的功能就只有 Vertex AI Studio 才有。&lt;/p&gt;

&lt;h2&gt;
  
  
  透過 Vertex AI API 取得切割結果
&lt;/h2&gt;

&lt;p&gt;如果你需要在程式中即時取得切割詞元的結果，也可以透過 &lt;a href="https://docs.cloud.google.com/vertex-ai/generative-ai/docs/multimodal/list-token" rel="noopener noreferrer"&gt;Vertex AI API&lt;/a&gt;，在 GenAI SDK 的 &lt;code&gt;Client&lt;/code&gt; 類別中，提供有 &lt;a href="https://googleapis.github.io/python-genai/genai.html#genai.models.AsyncModels.compute_tokens" rel="noopener noreferrer"&gt;&lt;code&gt;models.compute_tokens&lt;/code&gt;&lt;/a&gt; 方法可以取得切割資訊，它的參數和 &lt;code&gt;generate_content&lt;/code&gt; 相同，但會傳回 &lt;a href="https://googleapis.github.io/python-genai/genai.html#genai.types.ComputeTokensResponse" rel="noopener noreferrer"&gt;&lt;code&gt;ComputeTokensResponse&lt;/code&gt;&lt;/a&gt; 類物件，它的 tokens_info 屬性是一個 &lt;a href="https://googleapis.github.io/python-genai/genai.html#genai.types.TokensInfo" rel="noopener noreferrer"&gt;&lt;code&gt;TokensInfo&lt;/code&gt;&lt;/a&gt; 類物件的串列，個別代表輸入的 &lt;code&gt;contents&lt;/code&gt; 中每個 &lt;code&gt;content&lt;/code&gt; 的切割結果，其中 &lt;code&gt;token_ids&lt;/code&gt; 是詞元編號的串列、&lt;code&gt;tokens&lt;/code&gt; 是個別詞元對應的文字段落，&lt;code&gt;role&lt;/code&gt; 是發言角色。&lt;/p&gt;

&lt;p&gt;以下我們就依據上述結構，設計了一個&lt;a href="https://github.com/codemee/gemini_tokenizer" rel="noopener noreferrer"&gt;簡單的 CLI 程式&lt;/a&gt;，可以指定文字與模型，輸出切割結果：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rich.console&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="n"&gt;dotenv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;client_vertex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;vertexai&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;VERTEX_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;color_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#ccbfee&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#beedc6&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#f4d7ab&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#f4aeb1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# '4': '#a4dcf3',
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;console&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;用法：main.py prompt [model_name]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bold red&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-3-pro-preview&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client_vertex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compute_tokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;共 &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tokens_info&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;token_ids&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; 個 token：&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tokens_info&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;color_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color_map&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;bg_color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;color_map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#ffffff&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;on &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;bg_color&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;你可以像是這樣使用，如果沒有指定模型，預設會是 gemini-3-pro-preview：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜ uv run main.py "今天是偉大的日子" gemini-2.5-flash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;它會比照 Vertex AI Studio 的顏色顯示底色：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwulfr0eukejtz0d57kd5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwulfr0eukejtz0d57kd5.png" alt=" " width="205" height="46"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;我也在 HuggingFace 上部署了一個 &lt;a href="https://huggingface.co/spaces/flagtech/gemini_tokenizer" rel="noopener noreferrer"&gt;Gradio 的版本&lt;/a&gt;：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdtp56d9h5gvef6u95ob.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdtp56d9h5gvef6u95ob.png" alt=" " width="791" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;再次提醒，&lt;code&gt;models.compute_tokens&lt;/code&gt; 只有 Vertex AI API 才能使用，如果你使用 Gemini API，雖然看起來也可以叫用，但是只會傳回錯誤，告訴你這個方法只有 Vertex AI API 才支援。我不知道 Google 到底在想什麼，切割 token 的資訊都要 Vertex AI 才提供，政策沒有變更之前，你就只能透過上述方法取得相關資訊，還好，&lt;code&gt;models.compute_tokens&lt;/code&gt; 並不會號用詞元，所以不會產生費用。&lt;/p&gt;

&lt;p&gt;在我的觀察中，Gemini 的 tokenizer 不會把單一中文字元切開成多個詞元，非句首的英文單字也不大會切割成多個詞元，所以如果單純以詞元數來看，相同 context windows 下 Gemini 模型可以吃進入比 OpenAI 模型更多的文本，這也是大部分文章沒有提到的一點。&lt;/p&gt;

</description>
      <category>gemini</category>
      <category>tokenizer</category>
    </item>
    <item>
      <title>Colab 中在背景執行程式的方法</title>
      <dc:creator>codemee</dc:creator>
      <pubDate>Sat, 24 Jan 2026 03:59:37 +0000</pubDate>
      <link>https://dev.to/codemee/colab-zhong-zai-bei-jing-zhi-xing-cheng-shi-de-fang-fa-3kad</link>
      <guid>https://dev.to/codemee/colab-zhong-zai-bei-jing-zhi-xing-cheng-shi-de-fang-fa-3kad</guid>
      <description>&lt;p&gt;Colab 背後仰賴一個跑 Linux 的虛擬機器執行你的 Python 程式，如果要測試一些後端程式，其實也是沒有問題，尤其即使是免費用戶，也可以打開終端機直接操作背後的作業系統，非常方便。本文介紹在測試後端程式時常會需要在背景執行程式的方法。&lt;/p&gt;

&lt;h2&gt;
  
  
  直接開終端機下指令
&lt;/h2&gt;

&lt;p&gt;要在背景執行指令，最簡單的方法就是開啟終端機下指令，例如：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/content# sleep 10 &amp;amp;
[1] 7542
/content# 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;指令看起來會立即結束，如果以 &lt;code&gt;ps&lt;/code&gt; 指令檢查，就會看到在背景執行的指令：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/content# ps -eo pid,command | grep sleep
   7542 sleep 10
   7554 sleep 1
   7556 grep --color=auto sleep
/content#
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;等它結束後再度查詢：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/content# ps -eo pid,command | grep sleep
   7644 sleep 1
   7646 grep --color=auto sleep
[1]+  Done                    sleep 10
/content#
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;就會看到原本在背景執行的 &lt;code&gt;sleep 10&lt;/code&gt; 已經不見了，而在查詢指令結束後，也會出現已經結束的背景程式資訊。&lt;/p&gt;

&lt;h2&gt;
  
  
  使用 &lt;code&gt;!&lt;/code&gt; 執行指令
&lt;/h2&gt;

&lt;p&gt;Colab 本質是 Jupyter，提供有 &lt;code&gt;!&lt;/code&gt; 特殊命令可以執行系統指令，所以理論上可以 &lt;code&gt;!sleep 10 &amp;amp;&lt;/code&gt; 這樣執行背景程式：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqog0qokmoccppa0nw7q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqog0qokmoccppa0nw7q.png" alt=" " width="611" height="155"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;但你會發現儲存格會一直處在執行中狀態，直到背景程式結束：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc003sgrjw7qry357iars.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc003sgrjw7qry357iars.png" alt=" " width="616" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;你會看到儲存格的執行時間是 10 秒，這使得背景程式執行時無法執行其他儲存格。會發生這樣的狀況，是因為 &lt;code&gt;!&lt;/code&gt; 必須捕捉所執行程式的輸出，以便能夠顯示在儲存格的輸出區域，所以即使是以背景方式執行程式，但仍持續捕捉它的輸出，所以儲存格就會停留在執行中的狀態。&lt;/p&gt;

&lt;p&gt;要解決這個問題，最直接的方式就是把背景程式的輸出轉向，例如 &lt;code&gt;!sleep 10 &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &amp;amp;&lt;/code&gt;：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fysc6r03cuockcd03n2pi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fysc6r03cuockcd03n2pi.png" alt=" " width="619" height="119"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;你可以看到這裡儲存格的執行時間是 0 秒，也就是執行儲存格後就會離開執行中的狀態，即使背景程式仍在執行中，這樣就可以在背景執行必要的程式，但又可以執行其他儲存格了。要特別注意的是，轉向時，要把&lt;strong&gt;標準輸出&lt;/strong&gt;以及&lt;strong&gt;標準錯誤&lt;/strong&gt;都一併轉向。&lt;/p&gt;

&lt;p&gt;上述指令是把輸出都轉向到 Linux 的黑洞檔案 /dev/null 中，所以完全無法看到背景程式的輸出貨錯誤訊息。如果需要看到輸出結果，也可以轉向到任一檔案，例如 &lt;code&gt;! python -c "print 'hello'" &amp;gt; out.log 2&amp;gt;&amp;amp;1 &amp;amp;&lt;/code&gt;：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp3x88xemfbukpflyc2n1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp3x88xemfbukpflyc2n1.png" alt=" " width="710" height="193"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;就可以看到背景程式有噴出錯誤訊息，對於需要檢視後端程式輸出或除錯很有幫助。&lt;/p&gt;

&lt;h3&gt;
  
  
  使用 &lt;code&gt;nohup&lt;/code&gt; 協助轉向
&lt;/h3&gt;

&lt;p&gt;如果覺得上述輸出轉向語法有點複雜，也可以透過 &lt;code&gt;nohup&lt;/code&gt; 指令自動處理，這個指令原本是為了讓你可以在執行即使斷開當前終端機連線也會繼續執行的背景程式。前述的背景程式執行方法，會在你離開當前終端機階段（關閉終端機或是結束 ssh 連線等，稱為 &lt;strong&gt;hang up&lt;/strong&gt;，也是掛斷電話的意思）時一併結束，&lt;code&gt;nohangup&lt;/code&gt; 代表 "no hnag up"，表示不理會掛斷。&lt;code&gt;nohup&lt;/code&gt; 會幫你把輸出轉向到 &lt;code&gt;nohup.out&lt;/code&gt; 檔，例如 &lt;code&gt;!nohup sleep 10 &amp;amp;&lt;/code&gt;：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa28n2vour9w90pe5q71k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa28n2vour9w90pe5q71k.png" alt=" " width="708" height="144"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;執行後唯一的輸出就是告知輸出轉向檔案的訊息。&lt;/p&gt;

&lt;p&gt;要注意的是，&lt;code&gt;!&lt;/code&gt; 一樣會把儲存格輸出區的輸入轉向給執行的指令，如果沒有加上 &lt;code&gt;&amp;amp;&lt;/code&gt; 指定在背景執行，斷開儲存格輸入與指令的連結，一樣會處於等待輸入的狀態，像是 &lt;code&gt;!nohup sleep 10&lt;/code&gt;：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3mu3j5pc3ckbahfihly5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3mu3j5pc3ckbahfihly5.png" alt=" " width="711" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;就無法執行其他儲存格了。&lt;/p&gt;

</description>
      <category>colab</category>
      <category>linux</category>
    </item>
    <item>
      <title>遠端使用 ollama 的方法</title>
      <dc:creator>codemee</dc:creator>
      <pubDate>Mon, 19 Jan 2026 06:52:04 +0000</pubDate>
      <link>https://dev.to/codemee/yuan-duan-shi-yong-ollama-de-fang-fa-2j5g</link>
      <guid>https://dev.to/codemee/yuan-duan-shi-yong-ollama-de-fang-fa-2j5g</guid>
      <description>&lt;p&gt;ollama 除了可以在本機使用外，也可以從遠端連接，不過預設 ollama 只接受本機的連線，無法從遠端連接。&lt;/p&gt;

&lt;h2&gt;
  
  
  設定可接受遠端連線
&lt;/h2&gt;

&lt;p&gt;要讓 ollama 接受遠端連線，必須在啟動 ollama 服務前設定 &lt;code&gt;OLLAMA_HOST&lt;/code&gt; 環境變數為 &lt;code&gt;0.0.0.0&lt;/code&gt;，否則就只會接收本機連線。設定環境變數時可設定為 &lt;code&gt;0.0.0.0&lt;/code&gt; 保留預設連接埠 &lt;code&gt;11434&lt;/code&gt;，或是也可以同時指定連接埠，像是 &lt;code&gt;0.0.0.0:11434&lt;/code&gt;，不過不建議更改連接埠，以維持最大的相容性。&lt;/p&gt;

&lt;h3&gt;
  
  
  Window 環境
&lt;/h3&gt;

&lt;p&gt;在安裝完 ollama 後，你可以利用以下指令查看目前 ollama 監聽的 IP：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;netstat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ano&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;findstr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;":11434"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;輸出如下，可以看到目前只監聽本機迴路的 IP：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  TCP    127.0.0.1:3923         127.0.0.1:11434        TIME_WAIT       0
  TCP    127.0.0.1:11434        0.0.0.0:0              LISTENING       21544
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;也可以透過測試連線來確認，首先取得本機的 IP 位址：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Get-NetIPAddress&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;IPAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;InterfaceAlias&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;AddressFamily&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Where-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddressFamily&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-eq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'IPv4'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IPAddress      InterfaceAlias                     AddressFamily
---------      --------------                     -------------
172.19.144.1   vEthernet (WSL (Hyper-V firewall))          IPv4
169.254.130.47 區域連線* 3                                 IPv4
169.254.236.94 區域連線* 2                                 IPv4
169.254.221.5  藍牙網路連線                                IPv4
192.168.0.71   Wi-Fi                                       IPv4
127.0.0.1      Loopback Pseudo-Interface 1                 IPv4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;利用 curl 連線本機迴路測試：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;curl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http://127.0.0.1:11434/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;可正常運作：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ollama is running
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;但如果利用 Wi-Fi IP 連線：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;curl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http://192.168.0.71:11434/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;就會無法連線：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl: (7) Failed to connect to 192.168.0.71 port 11434 after 2032 ms: Could not connect to server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;為了讓 ollama 可以接受本機迴路以外的連線，你可以在使用者或是系統環境變數加入 &lt;code&gt;OLLAMA_HOST&lt;/code&gt;：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftpsfsv5b5wlq7g61w53j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftpsfsv5b5wlq7g61w53j.png" alt=" " width="417" height="188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;重新登入或是重新啟動後即可確認環境變數：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;OLLAMA_HOST&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;11434&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;再透過指令確認目前監聽的狀況：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;netstat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ano&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;findstr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;":11434"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;輸出如下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  TCP    0.0.0.0:11434          0.0.0.0:0              LISTENING       11832
  TCP    [::]:11434             [::]:0                 LISTENING       11832
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;即可看到監聽了所有的 IP，如果用 curl 測試：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;curl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http://192.168.0.71:11434/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Ollama&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;running&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;會看到可以正常連線。&lt;/p&gt;

&lt;h3&gt;
  
  
  Linux/MacOS 下手動啟動
&lt;/h3&gt;

&lt;p&gt;如果你沒有把 ollama 安裝成自動啟動的服務，就只要在使用者自己的 .bashrc 或是 .zshrc、.profile 檔中匯出環境變數即可，以下先取得本機 IP 位址：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip addr show eth0 | &lt;span class="nb"&gt;grep &lt;/span&gt;inet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;可以看到本機的 IP 是 172.19.149.141：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;inet 172.19.149.141/20 brd 172.19.159.255 scope global eth0
inet6 fe80::215:5dff:fe40:a05c/64 scope link 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;透過 curl 可以測試是否可連線：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl http://localhost:11434/
Ollama is running

curl http://172.19.149.141:11434/
curl: (7) Failed to connect to 172.19.149.141 port 11434 after 0 ms: Couldn't connect to server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;接著先把 ollama 停掉：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pkill ollama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;如果只是要短暫接受非本機連線，也可以直些設定環境變數，例如：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;OLLAMA_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.0.0.0 ollama serve &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;現在不論是本機或是非本機的 IP 都可以正常連線了：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:11434/
Ollama is running
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://172.19.149.141:11434/
Ollama is running
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;如果希望每次啟動 ollama 都會接收非本機的連線，就可以在 .bashrc、.profile 等 shell 的設定檔中加入：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OLLAMA_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.0.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;也可以達到一樣的效果，重新啟動 ollama 後，我從 Windows 連過去測試：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Invoke-WebRequest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Uri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://172.19.149.141:11434/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Content&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;Ollama&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;running&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;現在就通行無阻了。&lt;/p&gt;

&lt;h3&gt;
  
  
  Linux 下使用 systemctl 啟動的服務
&lt;/h3&gt;

&lt;p&gt;如果是以 &lt;code&gt;systemctl&lt;/code&gt; 啟動服務，必須到對應的 service 檔中設定環境變數，你可以在 /etc/systemd/system 或是 /usr/lib/systemd/system 下找到 ollama.service 檔：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/systemd/system/ollama.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;底下是我自己的範例，請在 &lt;code&gt;[Service]&lt;/code&gt; 區段中找到 Environment 項目，以 &lt;code&gt;"key=value"&lt;/code&gt; 的格式加入環境變數，我在這裡加入了 "OLLAMA_HOST=0.0.0.0:11434" 讓 ollama 會監聽所有的 IP。：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;連接埠 11434 是預設值，可以省略。&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[Unit]&lt;/span&gt;
&lt;span class="py"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Ollama Service&lt;/span&gt;
&lt;span class="py"&gt;After&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network-online.target&lt;/span&gt;

&lt;span class="nn"&gt;[Service]&lt;/span&gt;
&lt;span class="py"&gt;ExecStart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/bin/ollama serve&lt;/span&gt;
&lt;span class="py"&gt;User&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;ollama&lt;/span&gt;
&lt;span class="py"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;ollama&lt;/span&gt;
&lt;span class="py"&gt;Restart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;always&lt;/span&gt;
&lt;span class="py"&gt;RestartSec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;3&lt;/span&gt;
&lt;span class="py"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"PATH=&amp;lt;安裝時使用者的 PATH 路徑設定&amp;gt;"&lt;/span&gt; &lt;span class="s"&gt;"OLLAMA_HOST=0.0.0.0:11434"&lt;/span&gt;

&lt;span class="nn"&gt;[Install]&lt;/span&gt;
&lt;span class="py"&gt;WantedBy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;default.target&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;你也可以把 Environment 項目分成多行撰寫：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="py"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"PATH=&amp;lt;安裝時使用者的 PATH 路徑設定&amp;gt;"&lt;/span&gt; 
&lt;span class="s"&gt;Environment="OLLAMA_HOST=0.0.0.0:11434"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;注意：在 Linux 中，重新安裝是更新 Ollama 的唯一方法，但是重新安裝會蓋掉上述服務設定檔，所以請記得更新版本後，要重新修改設定檔，否則就無法從遠端連入使用 Ollama 了。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;修改完存檔後必須重新啟動服務才會生效，重新啟動前：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;net-tools
&lt;span class="nb"&gt;sudo &lt;/span&gt;netstat &lt;span class="nt"&gt;-anp&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;ollama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;會看到只監聽 &lt;code&gt;128.0.0.1&lt;/code&gt; 這個 IP 位址：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tcp        0      0 127.0.0.1:11434         0.0.0.0:*               LISTEN      120/ollama          
unix  3      [ ]         STREAM     CONNECTED     1342     120/ollama  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;接著重新啟動：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl daemon-reload
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart ollama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;確認是否有生效：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;netstat &lt;span class="nt"&gt;-anp&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;ollama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;輸出如下，現在監聽的是 &lt;code&gt;:::11434&lt;/code&gt;，沒有限定只有本機迴路的 IP 了：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tcp6       0      0 :::11434                :::*                    LISTEN      1092/ollama 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;現在除了以 localhost 或是 127.0.0.1 連接 ollama 外，也可以使用本機對外的 IP 位址：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip addr show eth0 | &lt;span class="nb"&gt;grep &lt;/span&gt;inet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;可看到像是如下的輸出：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;inet 172.19.149.141/20 brd 172.19.159.255 scope global eth0
inet6 fe80::215:5dff:fead:ec41/64 scope link
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;即可使用該 IP 測試：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://172.19.149.141:11434/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;看到以下訊息就表示成功：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ollama is running
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;你也可以到 Windows 的 PowerShell 測試了：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Invoke-WebRequest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Uri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://172.19.149.141:11434/"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ExpandProperty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Content&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;一樣可以取得同樣的結果：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ollama is running
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  macOS
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;注意：Ollama 目前在使用者介面上已經有 &lt;strong&gt;Expose OLLAMA to the network&lt;/strong&gt; 選項可以切換是否要讓外部連入，不用撰寫服務設定檔了。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mac 下比較特別：首先，在 .zshrc 等 shell 相關設定檔中設定的環境變數只對 shell 有效，但是 ollama 在 Mac 上是在使用者登入後透過帳戶的&lt;strong&gt;登入項目與延伸功能&lt;/strong&gt;的設定啟動 ollama 桌面程式（也就是你在工作列看到的小圖示），並且在 ollama 桌面程式的資源檔中設定執行 &lt;code&gt;ollama serve&lt;/code&gt; 指令啟動 ollama 服務，因此在 shell 的設定檔中所設定的環境變數完全不會生效。&lt;/p&gt;

&lt;p&gt;為了讓 ollama 服務啟動時可以依據環境變數接受非本機連線，我們必須改成使用 &lt;a href="https://www.launchd.info/" rel="noopener noreferrer"&gt;launchd&lt;/a&gt; 機制啟動 ollama 服務。首先，必須在 &lt;code&gt;~/Library/LaunchAgents/&lt;/code&gt; 建立一個&lt;code&gt;com.ollama.serve.plist&lt;/code&gt; 服務描述檔：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;plist&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Label&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;com.ollama.serve&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;ProgramArguments&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/Applications/Ollama.app/Contents/Resources/ollama&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;serve&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;EnvironmentVariables&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;OLLAMA_HOST&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;0.0.0.0:11434&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;RunAtLoad&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;KeepAlive&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;其中：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Label&lt;/strong&gt; 鍵：此服務的名稱。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ProgramArgs&lt;/strong&gt; 鍵：此服務要執行的指令。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EnvironmentVariables&lt;/strong&gt; 鍵：要提供給此服務執行時的環境變數&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;這個服務會在此帳號的使用者登入時啟動，要讓這個服務生效，必須先把已經在執行的 ollama 服務關閉：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;killall ollama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;然後使用 &lt;a href="https://ss64.com/mac/launchctl.html" rel="noopener noreferrer"&gt;launchctl&lt;/a&gt; 指令載入剛剛寫好的設定：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;launchctl load ~/Library/LaunchAgents/com.ollama.serve.plist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;載入後，就可以測試看看，先取得 IP：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ipconfig getifaddr en0
192.168.0.37
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;再利用 curl 工具測試：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://192.168.0.37:11434
Ollama is running
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;確認可以正常運作之後，還有最重要的一步，移除原本 ollama 桌面程式在登入後自動執行並啟動 ollama 服務的設定，否則 launchd 啟動服務時會因為已經有在監聽本機迴路的 ollama 而失敗：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faw9o8shjew5fzw70ukfo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faw9o8shjew5fzw70ukfo.png" alt=" " width="716" height="239"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;移除 ollama 項目後，之後重新開機登入此帳號，就會自動啟動剛剛設定的服務了。&lt;/p&gt;

&lt;p&gt;之後若是有修改服務的設定檔，就要先從系統中卸載之前載入的設定檔：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;launchctl unload ~/Library/LaunchAgents/com.ollama.serve.plist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;再重新載入設定檔即可。&lt;/p&gt;

&lt;h2&gt;
  
  
  使用 ollama 指令連接遠端的 ollama 服務
&lt;/h2&gt;

&lt;p&gt;只要設定 &lt;code&gt;OLLAMA_HOST&lt;/code&gt; 環境變數為遠端 ollama 服務的位址，就可以連接遠端 ollama 服務，例如：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;沒有設定 &lt;code&gt;OLLAMA_HOST&lt;/code&gt; 時，這是本機上 ollama 安裝的模型：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME                                                   ID              SIZE      MODIFIED    
weitsung50110/llama-3-taiwan:8b-instruct-dpo-q4_K_M    7fcf06fa5eaa    4.9 GB    5 days ago     
weitsung50110/multilingual-e5-large-instruct:f16       ad6d1b04ec00    1.1 GB    2 weeks ago    
gemma3:latest                                          a2af6cc3eb7f    3.3 GB    2 weeks ago    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;我們可以先設定環境變數（以下以 Linux 示範），再重新執行同樣的指令：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;OLLAMA_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.0.37 ollama list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;現在看到的則是我在 192.168.0.37 位址的 ollama 安裝的模型：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME                                                   ID              SIZE      MODIFIED       
gemma3:4b                                              a2af6cc3eb7f    3.3 GB    38 minutes ago    
weitsung50110/multilingual-e5-large-instruct:f16       ad6d1b04ec00    1.1 GB    3 hours ago       
weitsung50110/llama-3-taiwan:8b-instruct-dpo-q4_K_M    7fcf06fa5eaa    4.9 GB    3 hours ago       
gemma3:12b                                             f4031aab637d    8.1 GB    24 hours ago      
gemma3:1b                                              8648f39daa8f    815 MB    24 hours ago      
Darrrrr/mymodel:latest                                 40a13e3b82e2    815 MB    12 days ago       
deepseek-r1:14b                                        ea35dfe18182    9.0 GB    12 days ago       
qwq:latest                                             009cb3f08d74    19 GB     2 weeks ago       
gemma3:27b                                             a418f5838eaf    17 GB     2 weeks ago       
deepseek-r1:70b                                        0c1615a8ca32    42 GB     2 weeks ago       
deepseek-r1:32b                                        38056bbcbb2d    19 GB     2 weeks ago    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;這樣一來，你就可以彈性的配置實際要跑 ollama 模型的機器，其他的機器則只要透過遠端連線就可以使用同一組模型了。如果需要，你也可以直接在系統或是 shell 的設定檔中設定環境變數，就不需要每次執行都要先設定環境變數了。&lt;/p&gt;

&lt;h2&gt;
  
  
  使用 API 連接遠端的 ollama
&lt;/h2&gt;

&lt;p&gt;從遠端利用 API 使用 ollama：只要透過 API 位址的參數指定遠端 IP 即可，本例遠端 ollama 服務位於 &lt;code&gt;192.168.0.37&lt;/code&gt;：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://192.168.0.37:11434/api/chat &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
&amp;gt;   "model": "gemma3:4b",
&amp;gt;   "messages": [
&amp;gt;     {
&amp;gt;       "role": "user",
&amp;gt;       "content": "你好"
&amp;gt;     }
&amp;gt;   ],
&amp;gt;   "stream": false
&amp;gt; }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;可以取得正確結果：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"model":"gemma3:4b","created_at":"2025-04-30T09:48:53.946791Z","message":{"role":"assistant","content":"你好！很高兴和你聊天。有什么我可以帮助你的吗？\n"},"done_reason":"stop","done":true,"total_duration":361840209,"load_duration":57624667,"prompt_eval_count":10,"prompt_eval_duration":79502667,"eval_count":15,"eval_duration":224293500}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;使用 ollama 套件則是指定 &lt;code&gt;host&lt;/code&gt; 參數：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;ollama&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AsyncClient&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AsyncClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;http://192.168.0.37:11434&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gemma3:4b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;你是誰?&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;回應:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;若要使用 OpenAI API，必須傳入遠端 ollama 伺服器的位址連同&lt;strong&gt;連接埠&lt;/strong&gt;（預設為 &lt;code&gt;11434&lt;/code&gt;）給 &lt;code&gt;base_url&lt;/code&gt; 參數：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="c1"&gt;# 配置遠端 Ollama API
&lt;/span&gt;&lt;span class="n"&gt;OLLAMA_API_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://192.168.0.37:11434/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# 遠端 Ollama 伺服器
# OLLAMA_API_URL = "http://127.0.0.1:11434/v1"  # 本機 Ollama 伺服器
&lt;/span&gt;&lt;span class="n"&gt;MODEL_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemma3:12b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# 初始化 OpenAI 客戶端，指向 Ollama 的 API
&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OLLAMA_API_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 發送聊天完成請求
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MODEL_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;你好&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# 提取回應內容
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ollama</category>
    </item>
    <item>
      <title>讓 Claude Code 串接 Ollama 使用本地端模型</title>
      <dc:creator>codemee</dc:creator>
      <pubDate>Mon, 19 Jan 2026 06:43:34 +0000</pubDate>
      <link>https://dev.to/codemee/rang-claude-code-chuan-jie-ollama-shi-yong-ben-di-duan-mo-xing-5aph</link>
      <guid>https://dev.to/codemee/rang-claude-code-chuan-jie-ollama-shi-yong-ben-di-duan-mo-xing-5aph</guid>
      <description>&lt;p&gt;Ollama v0.14.0 後提供了&lt;a href="https://docs.ollama.com/api/anthropic-compatibility" rel="noopener noreferrer"&gt;與 Anthropic API 的相容性&lt;/a&gt;，這使得原本串接 Antropic API 的程式碼可以只接改用 Ollama 上的本地或雲端模型，同時也讓 &lt;a href="https://ollama.com/blog/claude" rel="noopener noreferrer"&gt;Claude Code 可以改用 Ollama 上的本地或地端模型&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;要讓 Claude Code 接上 Ollama，只要設定以下兩個環境變數：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export ANTHROPIC_AUTH_TOKEN=ollama
export ANTHROPIC_BASE_URL=http://&amp;lt;你的 Ollama 伺服器網址&amp;gt;:11434
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Windows 請改成：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$env:ANTHROPIC_AUTH_TOKEN="ollama"
$env:export ANTHROPIC_BASE_URL="http://&amp;lt;你的 Ollama 伺服器網址&amp;gt;:11434"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;如果要使用的是同一機器上的 Ollama 伺服器，伺服器網址寫 "localhost" 或是 "127.0.0.1" 都可以。如果是要使用其他台機上的 Ollama 伺服器，記得依照這篇&lt;a href="https://dev.to/codemee/yuan-duan-shi-yong-ollama-de-fang-fa-2j5g"&gt;遠端使用 ollama 的方法&lt;/a&gt;，讓 Ollama 伺服器可以接受遠端連線。&lt;/p&gt;

&lt;p&gt;以我自己的環境為例，Ollama 伺服器位於區網上的 192.168.0.150，安裝的模型如下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜ ollama list
NAME                 ID              SIZE      MODIFIED
gemma3:27b           a418f5838eaf    17 GB     3 weeks ago
gemma3:12b-it-qat    5d4fa005e7bb    8.9 GB    2 months ago
gpt-oss:120b         a951a23b46a1    65 GB     2 months ago
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;就可以如下執行 Claude Code：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜ claude --model gpt-oss:120b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;實際測試如下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; 你好

● 你好！有什么我可以帮助你的吗？

✻ Crunched for 56s

&amp;gt; 你現在使用哪一種模型？

● 我目前使用的是 gpt-oss:120b 模型。
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;以下則是 &lt;code&gt;/model&lt;/code&gt; 的輸出：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Select model
 Switch between Claude models. Applies to this session and future Claude Code sessions. For other/previous model
 names, specify with --model.

   1. Default (recommended)  Use the default model (currently Sonnet 4.5) · $3/$15 per Mtok
   2. Opus                   Opus 4.5 · Most capable for complex work · $5/$25 per Mtok
   3. Haiku                  Haiku 4.5 · Fastest for quick answers · $1/$5 per Mtok
 &amp;gt; 4. gpt-oss:120b √         Custom model

 Enter to confirm · escape to exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;除了本機端的模型，你也可以使用 Ollama 雲端的模型，例如以下先拉取所需的雲端模型資訊：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜ ollama pull minimax-m2.1:cloud
pulling manifest 
pulling 692f7c2439cc: 100% ▕█████████████████████████████████████████████████████████▏  378 B                         
verifying sha256 digest 
writing manifest 
success
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;然後讓 Ollama 伺服器登入你的帳號以便取用雲端模型：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜ ollama signin
You need to be signed in to Ollama to run Cloud models.

To sign in, navigate to:
    https://ollama.com/connect?name=ubuntu&amp;amp;key=c3NoLWVk...3NlYno
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;完成後即可使用剛剛拉取下來的雲端模型：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜ claude --model minimax-m2.1:cloud
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;實測結果如下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; 你好

✽ Beboppin'… (ctrl+c to interrupt)

● 你好！有什麼我可以幫你的嗎？

&amp;gt; 你使用哪一種模型？

● 我使用的是 minimax-m2.1:cloud 模型
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>claudecode</category>
      <category>ollama</category>
    </item>
    <item>
      <title>Claude Code MCPSearch 工具</title>
      <dc:creator>codemee</dc:creator>
      <pubDate>Sat, 17 Jan 2026 04:28:16 +0000</pubDate>
      <link>https://dev.to/codemee/claude-code-mcpsearch-gong-ju-409e</link>
      <guid>https://dev.to/codemee/claude-code-mcpsearch-gong-ju-409e</guid>
      <description>&lt;p&gt;Claude Code 在 &lt;a href="https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md#217" rel="noopener noreferrer"&gt;2.1.7&lt;/a&gt; 版時改成預設啟用 &lt;strong&gt;MCPSearch&lt;/strong&gt; 工具，它會在你的 MCP 工具資訊佔用的 token 數達到 context window 的 &lt;strong&gt;10%（預設值）&lt;/strong&gt; 時干預 MCP 工具的使用方式，最主要有兩個效應：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;延後把 MCP 工具的資訊加入 contex 的時間&lt;/strong&gt;：只有在模型判斷目前資訊無法完成任務時，才會使用 MCPSearch 工具搜尋是否有適當的 MCP 工具可用，這時才會根據 MCPSearch 工具的搜尋結果載入 MCP 工具的資訊。優點就是在不需要使用 MCP 工具的情況下，不論你連接了多少個 MCP 伺服器，都完全不佔用 contex window。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;只會提供所需工具的資訊&lt;/strong&gt;，不會把所屬 MCP 伺服器的所有工具的資訊都加入 context。也就是說，如果某個 MCP 伺服器提供有 10 個工具，但只需要用到其中一項工具時，就只會提供給模型該項工具的資訊參考，不會把 10 個工具的資訊都放入 context 中，無端佔用額外的 contex window。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;有興趣可以參考 Claude 中相對應的 &lt;a href="https://www.anthropic.com/engineering/advanced-tool-use#tool-search-tool" rel="noopener noreferrer"&gt;Tool Search 工具&lt;/a&gt; 的說明。&lt;/p&gt;

&lt;h2&gt;
  
  
  以 Notion MCP 伺服器實測
&lt;/h2&gt;

&lt;p&gt;你很容易就可以發現為什麼要預設啟用 MCPSearch 工具，以 Notion 官方的 MCP 伺服器為例，即使我的 Claude Code 只連接了這一個 MCP 伺服器：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜ claude mcp list
Checking MCP server health...

notion: https://mcp.notion.com/mcp (HTTP) - ✓ Connected
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;當你以 &lt;code&gt;/context&lt;/code&gt; 查看時：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Context Usage
⛁ ⛀ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁   claude-opus-4-5-20251101 · 41k/200k tokens (21%)
⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁   ⛁ System prompt: 3.0k tokens (1.5%)
⛀ ⛀ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛁ System tools: 17.0k tokens (8.5%)
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛁ MCP tools: 21.1k tokens (10.6%)
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛁ Messages: 8 tokens (0.0%)
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛶ Free space: 114k (56.9%)
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛝ Autocompact buffer: 45.0k tokens (22.5%)
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛝ ⛝ ⛝
⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝
⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝

MCP tools · /mcp
└ mcp__notion__notion-search: 1.5k tokens
└ mcp__notion__notion-fetch: 304 tokens
└ mcp__notion__notion-create-pages: 2.0k tokens
└ mcp__notion__notion-update-page: 2.0k tokens
└ mcp__notion__notion-move-pages: 611 tokens
└ mcp__notion__notion-duplicate-page: 220 tokens
└ mcp__notion__notion-create-database: 5.8k tokens
└ mcp__notion__notion-update-database: 6.0k tokens
└ mcp__notion__notion-create-comment: 1.6k tokens
└ mcp__notion__notion-get-comments: 108 tokens
└ mcp__notion__notion-get-teams: 229 tokens
└ mcp__notion__notion-get-users: 452 tokens
└ mcp__notion__notion-get-self: 79 tokens
└ mcp__notion__notion-get-user: 120 tokens                                 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;會發現光是 Notion 提供的 MCP 工具就有 14 個，總共耗用 21.1k 個 token，比所有系統（內建）工具的 17.0k 還多。當然，這樣的好處是模型可參考所有工具的資訊，直接挑選適當的使用，例如：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; 我有哪些跟提案相關的筆記？

● notion - notion-search (MCP)(query: "提案", query_type: "internal")

───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 Tool use

   notion - notion-search(query: "提案", query_type: "internal") (MCP)
   Perform a search over:
...（略）
 Do you want to proceed?
 &amp;gt; 1. Yes
   2. Yes, and don't ask again for notion - notion-search commands in C:\Users\meebo\code\tt
   3. No

 Esc to cancel · Tab to add additional instruction
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;你可以看到模型根據問題，馬上找出可以使用 Notion 提供的搜尋工具協助處理，但壞處就是如果提問內容根本不需要 MCP 工具的協助，還是得佔用這 21.1k 個 token 的空間，白白燒掉 token 額度。&lt;/p&gt;

&lt;p&gt;我們沒有要真的測試 Notion 的工具效果，所以這裡先中斷離開 Claude Code。&lt;/p&gt;

&lt;h2&gt;
  
  
  使用 MCPSearch 工具
&lt;/h2&gt;

&lt;p&gt;接著來看看如果啟用 MCPSearch 工具，會有什麼差別？要特別注意的是，雖然官方文件說預設會啟用 MCPSearch 工具，不過我自己的測試環境中，是已經升級到 2.1.11 的版本，但並不會自動啟用 MCPSearch 工具：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜ claude --version
2.1.11 (Claude Code)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;在 Claude Code 的 &lt;a href="https://github.com/anthropics/claude-code/issues" rel="noopener noreferrer"&gt;Github issue&lt;/a&gt; 頁面中，找到其他人類似的問題，提供了&lt;a href="https://github.com/anthropics/claude-code/issues/18370#issuecomment-3756355289" rel="noopener noreferrer"&gt;繞路的解法&lt;/a&gt;，設定環境變數 &lt;code&gt;ENABLE_TOOL_SEARCH&lt;/code&gt; 為 &lt;code&gt;true&lt;/code&gt; 就可以強制啟用 MCPSearch 工具，底下是我在 Windows 的 PowerShell 下測試：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜ $env:ENABLE_TOOL_SEARCH="true"; claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;如果使用 macOS/Linux，就改用：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ENABLE_TOOL_SEARCH=true claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;如果覺得麻煩，也可以在 .claude/settings.json 檔中加入環境變數的設定：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ENABLE_TOOL_SEARCH"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"true"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;執行後一樣使用 &lt;code&gt;/context&lt;/code&gt; 觀察目前的 contex 用量：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Context Usage
⛁ ⛀ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁   claude-opus-4-5-20251101 · 20k/200k tokens (10%)
⛀ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛁ System prompt: 3.1k tokens (1.5%)
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛁ System tools: 17.0k tokens (8.5%)
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛁ Messages: 8 tokens (0.0%)
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛶ Free space: 135k (67.5%)
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛝ Autocompact buffer: 45.0k tokens (22.5%)
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛝ ⛝ ⛝
⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝
⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝

MCP tools · /mcp (loaded on-demand)

Available
└ mcp__notion__notion-search
└ mcp__notion__notion-fetch
└ mcp__notion__notion-create-pages
└ mcp__notion__notion-update-page
└ mcp__notion__notion-move-pages
└ mcp__notion__notion-duplicate-page
└ mcp__notion__notion-create-database
└ mcp__notion__notion-update-database
└ mcp__notion__notion-create-comment
└ mcp__notion__notion-get-comments
└ mcp__notion__notion-get-teams
└ mcp__notion__notion-get-users
└ mcp__notion__notion-get-self
└ mcp__notion__notion-get-user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;你可以看到兩個主要的差異：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;在上方的分類 token 用量統計中，原本佔用 21.1k 個 token 的 MCP tools 不見了，總用量也從原本看到的 41k 驟降成 20k，少掉的就是 MCP Tools 的 21.1k。&lt;/li&gt;
&lt;li&gt;在底下標示 &lt;strong&gt;MCP tools&lt;/strong&gt; 的區域，出現了 &lt;strong&gt;"（loaded on-emand）"&lt;/strong&gt; 字樣，表示現在是依據需要才會載入 MCP 工具的資訊到 context 中。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;很顯然 MCPSearch 生效了，不確定會需要使用 MCP 工具時，就不會把 MCP 工具放入 context 中。接著就來驗證看看：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; 我有哪些跟提案相關的筆記？

● 讓我搜尋你的 Notion 筆記中與提案相關的內容。

● MCPSearch(Search MCP tools: "select:mcp__notion__notion-search")
  ⎿  Found 1 tool

● notion - notion-search (MCP)(query: "提案", query_type: "internal")

───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 Tool use

   notion - notion-search(query: "提案", query_type: "internal") (MCP)
...（略）
 Do you want to proceed?
 &amp;gt; 1. Yes
   2. Yes, and don't ask again for notion - notion-search commands in C:\Users\meebo\code\tt
   3. No

 Esc to cancel · Tab to add additional instructions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;我們問了同樣的問題，你會看到最終模型還是會使用 Notion 伺服器提供的搜尋工具，但是過程不大一樣：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;模型先使用了 MCPSearch 工具，它的執行結果是 ""select:mcp_&lt;em&gt;notion&lt;/em&gt;_notion-search")"，告訴模型可以選用 Notion 的搜尋工具。&lt;/li&gt;
&lt;li&gt;接著模型依據 MCPSeach 工具的搜尋結果使用 Notion 的搜尋工具。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;事情還不只如此，即使現在使用到了 Notion 伺服器提供的工具，如果中斷剛剛的交談，再使用 &lt;code&gt;/context&lt;/code&gt; 查看用量：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Context Usage
⛁ ⛀ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁   claude-opus-4-5-20251101 · 22k/200k tokens (11%)
⛁ ⛀ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛁ System prompt: 3.0k tokens (1.5%)
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛁ System tools: 17.0k tokens (8.5%)
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛁ MCP tools: 1.5k tokens (0.8%)
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛁ Messages: 685 tokens (0.3%)
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛶ Free space: 133k (66.4%)
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛝ Autocompact buffer: 45.0k tokens (22.5%)
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛝ ⛝ ⛝
⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝
⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝ ⛝

MCP tools · /mcp (loaded on-demand)

Loaded
└ mcp__notion__notion-search: 1.5k tokens

Available
└ mcp__notion__notion-fetch
└ mcp__notion__notion-create-pages
└ mcp__notion__notion-update-page
└ mcp__notion__notion-move-pages
└ mcp__notion__notion-duplicate-page
└ mcp__notion__notion-create-database
└ mcp__notion__notion-update-database
└ mcp__notion__notion-create-comment
└ mcp__notion__notion-get-comments
└ mcp__notion__notion-get-teams
└ mcp__notion__notion-get-users
└ mcp__notion__notion-get-self
└ mcp__notion__notion-get-user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;你會看到兩個不同的地方：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;上方分類統計用量的地方出現了 &lt;strong&gt;MCP tools&lt;/strong&gt;，但是總量是 1.5k，不是最前面看到的 21.1k，表示並不是所有 Notion 提供的工具資訊都放入了 context。&lt;/li&gt;
&lt;li&gt;在下方標示 &lt;strong&gt;MCP tools&lt;/strong&gt; 的地方，會看到多了 &lt;strong&gt;Loaded&lt;/strong&gt; 區塊，這裡只列出了 &lt;code&gt;mcp__notion__notion-search&lt;/code&gt;，佔用 1.5k 個 token。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;正因為如此，所以雖然用到了 MCP 工具，但是 context 總量也還是只有 22k 而已，不會激增到最前面看到的 41k。&lt;/p&gt;

&lt;h2&gt;
  
  
  MCPSearch 工具的代價
&lt;/h2&gt;

&lt;p&gt;MCPSearch 工具的基本概念很簡單，它想做到的就是像 &lt;a href="https://agentskills.io/what-are-skills" rel="noopener noreferrer"&gt;Agent Skills&lt;/a&gt; 那樣，只有在需要的時候才提供完整資訊。如果 MCP 工具使用到的機率不高，廣度也不大，也就是不會一下要用 A 工具、一下要用 B 工具，一下又要用 C 工具，那麼沒有用到 MCP 工具時所省下的 token 量，應該可以讓你節省很多額度，代價則是在新的交談階段初次使用到特定的 MCP 工具前，都會先使用一次 MCPSearch 工具，多進行一次交談。&lt;/p&gt;

&lt;p&gt;從上面的測試也可以看到，就算只連接了一個 MCP 伺服器，但如果提供的工具繁多，或是該工具比較複雜，那麼相關的資訊量也是可以多到你嚇一跳的。單單一個 Notion 伺服器提供的工具就佔了 21.1k 個 token，整個 context window 也才 200k，10%↑ 的量就不見了，是很有感的差異，更別說你可能連接了不只一個 MCP 伺服器。&lt;/p&gt;

&lt;p&gt;當然，如果你就只會連接佔用量很少的 MCP 伺服器，整體用量可能比多一輪問答使用 MCPSearch 工具的 token 量（這會包含交談記錄、系統訊息、系統工具）少很多，或者使用到 MCP 工具的機率非常頻繁，那就可以權衡是否要啟用 MCPSearch 工具。&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>claude</category>
      <category>mcp</category>
      <category>mcpsearch</category>
    </item>
    <item>
      <title>VScode 的自動執行機制--Tasks</title>
      <dc:creator>codemee</dc:creator>
      <pubDate>Mon, 12 Jan 2026 04:13:37 +0000</pubDate>
      <link>https://dev.to/codemee/vscode-de-zi-dong-zhi-xing-ji-zhi-tasks-387j</link>
      <guid>https://dev.to/codemee/vscode-de-zi-dong-zhi-xing-ji-zhi-tasks-387j</guid>
      <description>&lt;p&gt;由於看到一篇&lt;a href="https://www.threads.com/@haocherhong/post/DTPM7njkY-T?xmt=AQF0HNlVISd5EVEg8w_Oq54PRhVkeP9-z9h2SoaMy77kSJo" rel="noopener noreferrer"&gt;科技詐騙的文章&lt;/a&gt;，才知道 VSCode 開啟資料夾時問的『是否信任此資料夾』原來很重要。這個詐騙成功的關鍵首先是 VSCode 執行&lt;a href="https://code.visualstudio.com/docs/debugtest/tasks" rel="noopener noreferrer"&gt;任務&lt;/a&gt;的機制，原始的目的是方便大家設計好可以建置環境、編譯、測試專案的指令，不需要自己再去終端機敲長串的指令，但要命的是這個機制可以設定成 VSCode 開啟資料夾時就&lt;a href="https://code.visualstudio.com/docs/debugtest/tasks#_run-behavior" rel="noopener noreferrer"&gt;自動執行&lt;/a&gt;，對於從像是 GutHub 複製下來的專案，增添了極高的風險。&lt;/p&gt;

&lt;h2&gt;
  
  
  自動執行任務的機制
&lt;/h2&gt;

&lt;p&gt;VSCode 可以在 .vscode 下放置 tasks.json，格式如下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;See&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;https://go.microsoft.com/fwlink/?LinkId=&lt;/span&gt;&lt;span class="mi"&gt;733558&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;documentation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;about&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tasks.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;format&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"play"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"uv run main.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"runOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"runOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"folderOpen"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;其中：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;type&lt;/code&gt; 項目可以搭配一些開發環境設定，執行特定的開發工具。若設定為 "shell"，就可以自由執行任何指令。&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;runOptions&lt;/code&gt; 則可以用來設定執行選項，像是 &lt;code&gt;runOn&lt;/code&gt; 就可以設定為 "folderOpen"，只要用 VSCode 開啟該資料夾就會自動執行，這就可以用來執行自動清除快取之類的任務。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;不過因為可以自動執行，所以如果埋了一個惡意程式，就可能會傷害你的電腦，甚至暗中安裝常駐的惡意程式之類。&lt;/p&gt;

&lt;p&gt;這個自動執行機制還可以透過 &lt;code&gt;presentation&lt;/code&gt; 屬性設定得更隱密：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;See&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;https://go.microsoft.com/fwlink/?LinkId=&lt;/span&gt;&lt;span class="mi"&gt;733558&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;documentation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;about&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tasks.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;format&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"play"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"uv run main.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"runOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"runOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"folderOpen"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"presentation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"reveal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"never"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"revealProblems"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"never"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"close"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;其中：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;reveal&lt;/code&gt;：控制是否要顯示執行任務的終端機面板。&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;revealProblem&lt;/code&gt;：則是控制執行有問題時，是否要顯示問題面板。&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;close&lt;/code&gt;：控制執行完任務後是否要關閉終端機。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;只要設定都不顯示面板，而且執行後關閉終端機，除非程式本身開啟額外的視窗、或非常佔用資源等等，否則就很難發現它的蹤跡。&lt;/p&gt;

&lt;h2&gt;
  
  
  避免自動執行任務的危險
&lt;/h2&gt;

&lt;p&gt;要避免上述問題，最簡單的方式就是每次開啟新的資料夾時，都不要信任該資料夾。如果已經信任過資料夾，也可以按 Ctrl+Shift+C開啟&lt;strong&gt;命令選擇區&lt;/strong&gt;後執行 &lt;strong&gt;manage workspace trust&lt;/strong&gt; 命令進入設定頁面，再按&lt;strong&gt;不信任&lt;/strong&gt;，&lt;/p&gt;

&lt;p&gt;如果是因為父資料夾受信任而自動信任子資料夾，就要到父資料夾中設定。或者也可以在同一設定頁面下的&lt;strong&gt;信任的資料夾與工作區&lt;/strong&gt;中，從清單中移除已被信任的資料夾。&lt;/p&gt;

&lt;p&gt;如果需要信任資料夾的好處，不想動到資校夾或工作區的信任設定，也可以修改允許自動執行任務的設定，你可以在工作區的設定檔 .vscode/settings.json 中加上如下的設定：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"task.allowAutomaticTasks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"off"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;就不會自動執行任務。你也可以加到使用者設定檔中，避免從網路下載 repo 後，一時忘記就直接開啟，釀成大禍。之後若真的需要執行特定的任務，可以到&lt;strong&gt;命令選擇區&lt;/strong&gt;中執行 &lt;strong&gt;Run Task&lt;/strong&gt; 命令，選擇要執行的任務即可。&lt;/p&gt;

&lt;p&gt;要注意的是，像是 Cursor 這個延伸自 VSCode 的編輯器，預設是不啟用信任機制的，也就是完全信任所有的資料夾，不可不小心。&lt;/p&gt;

</description>
      <category>vscode</category>
    </item>
    <item>
      <title>PowerShell pipeline chain operator 的小陷阱</title>
      <dc:creator>codemee</dc:creator>
      <pubDate>Fri, 12 Dec 2025 01:38:08 +0000</pubDate>
      <link>https://dev.to/codemee/powershell-pipeline-chain-operator-de-xiao-xian-jing-3d67</link>
      <guid>https://dev.to/codemee/powershell-pipeline-chain-operator-de-xiao-xian-jing-3d67</guid>
      <description>&lt;p&gt;PowerShell 7 提供有&lt;a href="https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_pipeline_chain_operators?view=powershell-7.5" rel="noopener noreferrer"&gt;pipeline chain operator&lt;/a&gt;，也就是 &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; 與 &lt;code&gt;||&lt;/code&gt;，不過使用上必須注意，不然就會遇到意外的結果。&lt;/p&gt;

&lt;h2&gt;
  
  
  運算子的兩端都要是指令
&lt;/h2&gt;

&lt;p&gt;看到 &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; 與 &lt;code&gt;||&lt;/code&gt;，很容易就會寫出類似這樣的指令：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="err"&gt;➜&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;\temp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;exit&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;不過這會得到以下錯誤訊息：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;exit: The term 'exit' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;這是因為 &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; 與 &lt;code&gt;||&lt;/code&gt; 的左右兩邊都要是指令（包含 cmdlet、函式、腳本檔、外部程式等），但 &lt;code&gt;exit&lt;/code&gt; 是 PowerShell 的保留字，在語法上是陳述句，並不是指令，所以你可以看到錯誤訊息明確表示無法執行 &lt;code&gt;exit&lt;/code&gt;。&lt;/p&gt;

&lt;h2&gt;
  
  
  沒有 pipeline 的功能
&lt;/h2&gt;

&lt;p&gt;這組運算子名稱中的 "pipeline" 也很容易誤解，以為他們是有條件的 pipeline，例如，你可能會期望以下指令可以在 &lt;code&gt;\temp&lt;/code&gt;  資料夾存在的情況下，將資料夾內的檔案清單傳給右邊的 &lt;code&gt;measure-object&lt;/code&gt;：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="err"&gt;➜&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test-path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;\temp&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;True&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;➜&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ls&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;\temp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Measure-Object&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;但其實並不會，你會看到類似以下的結果：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    Directory: C:\temp

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----         2025/12/9 下午 04:23                F6722
d----        2025/12/11 下午 10:49                test_wt
d----        2025/12/11 下午 10:45                tmr
-a---         2025/5/22 下午 10:50            162 tomica.jpg
-a---         2025/3/18 下午 04:55         521370 train1.jpeg
-a---         2025/3/18 下午 04:55         879688 train2.jpeg
-a---         2025/8/29 下午 11:56       10824402 VVAICar_Test.apk

Count             : 0
Average           : 
Sum               : 
Maximum           : 
Minimum           : 
StandardDeviation : 
Property          : 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;也就是 pipeline chain operator 只會串接指令，但不會傳送輸出結果，如果命名為 chain operator 好像比較適當。&lt;/p&gt;

</description>
      <category>powershell</category>
      <category>pipeline</category>
    </item>
    <item>
      <title>遠端使用 ollama 的方法</title>
      <dc:creator>codemee</dc:creator>
      <pubDate>Fri, 01 Aug 2025 05:42:48 +0000</pubDate>
      <link>https://dev.to/codemee/yuan-duan-shi-yong-ollama-de-fang-fa-53d0</link>
      <guid>https://dev.to/codemee/yuan-duan-shi-yong-ollama-de-fang-fa-53d0</guid>
      <description>&lt;p&gt;ollama 除了可以在本機使用外，也可以從遠端連接，不過預設 ollama 只接受本機的連線，無法從遠端連接。&lt;/p&gt;

&lt;h2&gt;
  
  
  設定可接受遠端連線
&lt;/h2&gt;

&lt;p&gt;要讓 ollama 接受遠端連線，必須在啟動 ollama 服務前設定 &lt;code&gt;OLLAMA_HOST&lt;/code&gt; 環境變數為 &lt;code&gt;0.0.0.0&lt;/code&gt;，否則就只會接收本機連線。設定環境變數時可設定為 &lt;code&gt;0.0.0.0&lt;/code&gt; 保留預設連接埠 &lt;code&gt;11434&lt;/code&gt;，或是也可以同時指定連接埠，像是 &lt;code&gt;0.0.0.0:11434&lt;/code&gt;，不過不建議更改連接埠，以維持最大的相容性。&lt;/p&gt;

&lt;h3&gt;
  
  
  Window 環境
&lt;/h3&gt;

&lt;p&gt;在安裝完 ollama 後，你可以利用以下指令查看目前 ollama 監聽的 IP：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;netstat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ano&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;findstr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;":11434"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;輸出如下，可以看到目前只監聽本機迴路的 IP：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  TCP    127.0.0.1:3923         127.0.0.1:11434        TIME_WAIT       0
  TCP    127.0.0.1:11434        0.0.0.0:0              LISTENING       21544
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;也可以透過測試連線來確認，首先取得本機的 IP 位址：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Get-NetIPAddress&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;IPAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;InterfaceAlias&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;AddressFamily&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Where-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddressFamily&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-eq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'IPv4'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IPAddress      InterfaceAlias                     AddressFamily
---------      --------------                     -------------
172.19.144.1   vEthernet (WSL (Hyper-V firewall))          IPv4
169.254.130.47 區域連線* 3                                 IPv4
169.254.236.94 區域連線* 2                                 IPv4
169.254.221.5  藍牙網路連線                                IPv4
192.168.0.71   Wi-Fi                                       IPv4
127.0.0.1      Loopback Pseudo-Interface 1                 IPv4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;利用 curl 連線本機迴路測試：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;curl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http://127.0.0.1:11434/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;可正常運作：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ollama is running
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;但如果利用 Wi-Fi IP 連線：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;curl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http://192.168.0.71:11434/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;就會無法連線：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl: (7) Failed to connect to 192.168.0.71 port 11434 after 2032 ms: Could not connect to server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;為了讓 ollama 可以接受本機迴路以外的連線，你可以在使用者或是系統環境變數加入 &lt;code&gt;OLLAMA_HOST&lt;/code&gt;：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy9qpsj9h4qse4rmmuddj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy9qpsj9h4qse4rmmuddj.png" alt="圖片" width="417" height="188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;重新登入或是重新啟動後即可確認環境變數：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;OLLAMA_HOST&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;11434&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;再透過指令確認目前監聽的狀況：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;netstat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ano&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;findstr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;":11434"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;輸出如下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  TCP    0.0.0.0:11434          0.0.0.0:0              LISTENING       11832
  TCP    [::]:11434             [::]:0                 LISTENING       11832
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;即可看到監聽了所有的 IP，如果用 curl 測試：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;curl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http://192.168.0.71:11434/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Ollama&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;running&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;會看到可以正常連線。&lt;/p&gt;

&lt;h3&gt;
  
  
  Linux/MacOS 下手動啟動
&lt;/h3&gt;

&lt;p&gt;如果你沒有把 ollama 安裝成自動啟動的服務，就只要在使用者自己的 .bashrc 或是 .zshrc、.profile 檔中繪出環境變數即可，以下先取得本機 IP 位址：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip addr show eth0 | &lt;span class="nb"&gt;grep &lt;/span&gt;inet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;可以看到本機的 IP 是 172.19.149.141：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;inet 172.19.149.141/20 brd 172.19.159.255 scope global eth0
inet6 fe80::215:5dff:fe40:a05c/64 scope link 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;透過 curl 可以測試是否可連線：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl http://localhost:11434/
Ollama is running

curl http://172.19.149.141:11434/
curl: (7) Failed to connect to 172.19.149.141 port 11434 after 0 ms: Couldn't connect to server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;接著先把 ollama 停掉：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pkill ollama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;如果只是要短暫接受非本機連線，也可以直些設定環境變數，例如：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;OLLAMA_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.0.0.0 ollama serve &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;現在不論是本機或是非本機的 IP 都可以正常連線了：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:11434/
Ollama is running
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://172.19.149.141:11434/
Ollama is running
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;如果希望每次啟動 ollama 都會接收非本機的連線，就可以在 .bashrc、.profile 等 shell 的設定檔中加入：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OLLAMA_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.0.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;也可以達到一樣的效果，重新啟動 ollama 後，我從 Windows 連過去測試：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Invoke-WebRequest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Uri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://172.19.149.141:11434/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Content&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;Ollama&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;running&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;現在就通行無阻了。&lt;/p&gt;

&lt;h3&gt;
  
  
  Linux 下使用 systemctl 啟動的服務
&lt;/h3&gt;

&lt;p&gt;如果是以 &lt;code&gt;systemctl&lt;/code&gt; 啟動服務，必須到對應的 service 檔中設定環境變數，你可以在 /etc/systemd/system 或是 /usr/lib/systemd/system 下找到 ollama.service 檔：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/systemd/system/ollama.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;底下是我我自己的範例，請在 &lt;code&gt;[Service]&lt;/code&gt; 區段中找到 Environment 項目，以 &lt;code&gt;"key=value"&lt;/code&gt; 的格式加入環境變數，我在這裡加入了 "OLLAMA_HOST=0.0.0.0:11434" 讓 ollama 會監聽所有的 IP。：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[Unit]&lt;/span&gt;
&lt;span class="py"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Ollama Service&lt;/span&gt;
&lt;span class="py"&gt;After&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network-online.target&lt;/span&gt;

&lt;span class="nn"&gt;[Service]&lt;/span&gt;
&lt;span class="py"&gt;ExecStart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/bin/ollama serve&lt;/span&gt;
&lt;span class="py"&gt;User&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;ollama&lt;/span&gt;
&lt;span class="py"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;ollama&lt;/span&gt;
&lt;span class="py"&gt;Restart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;always&lt;/span&gt;
&lt;span class="py"&gt;RestartSec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;3&lt;/span&gt;
&lt;span class="py"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"PATH=/home/meebox/.local/bin:/home/meebox/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/wsl/lib:/mnt/c/users/meebo/scoop/apps/vscode/current/bin"&lt;/span&gt; &lt;span class="s"&gt;"OLLAMA_HOST=0.0.0.0:11434"&lt;/span&gt;

&lt;span class="nn"&gt;[Install]&lt;/span&gt;
&lt;span class="py"&gt;WantedBy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;default.target&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;修改完存檔後必須重新啟動服務才會生效，重新啟動前：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;net-tools
&lt;span class="nb"&gt;sudo &lt;/span&gt;netstat &lt;span class="nt"&gt;-anp&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;ollama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;會看到只監聽 &lt;code&gt;128.0.0.1&lt;/code&gt; 這個 IP 位址：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tcp        0      0 127.0.0.1:11434         0.0.0.0:*               LISTEN      120/ollama          
unix  3      [ ]         STREAM     CONNECTED     1342     120/ollama  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;接著重新啟動：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl daemon-reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;確認是否有生效：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;netstat &lt;span class="nt"&gt;-anp&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;ollama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;輸出如下，現在監聽的是 &lt;code&gt;:::11434&lt;/code&gt;，沒有限定只有本機迴路的 IP 了：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tcp6       0      0 :::11434                :::*                    LISTEN      1092/ollama 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;現在除了以 localhost 或是 127.0.0.1 連接 ollama 外，也可以使用本機對外的 IP 位址：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip addr show eth0 | &lt;span class="nb"&gt;grep &lt;/span&gt;inet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;可看到像是如下的輸出：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;inet 172.19.149.141/20 brd 172.19.159.255 scope global eth0
inet6 fe80::215:5dff:fead:ec41/64 scope link
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;即可使用該 IP 測試：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://172.19.149.141:11434/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;看到以下訊息就表示成功：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ollama is running
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;你也可以到 Windows 的 PowerShell 測試了：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Invoke-WebRequest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Uri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://172.19.149.141:11434/"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ExpandProperty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Content&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;一樣可以取得同樣的結果：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ollama is running
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  MacOS
&lt;/h3&gt;

&lt;p&gt;Mac 下比較特別：首先，在 .zshrc 等 shell 相關設定檔中設定的環境變數只對 shell 有效，但是 ollama 在 Mac 上是在使用者登入後透過帳戶的&lt;strong&gt;登入項目與延伸功能&lt;/strong&gt;的設定啟動 ollama 桌面程式（也就是你在工作列看到的小圖示），並且在 ollama 桌面程式的資源檔中設定執行 &lt;code&gt;ollama serve&lt;/code&gt; 指令啟動 ollama 服務，因此在 shell 的設定檔中所設定的環境變數完全不會生效。&lt;/p&gt;

&lt;p&gt;為了讓 ollama 服務啟動時可以依據環境變數接受非本機連線，我們必須改成使用 &lt;a href="https://www.launchd.info/" rel="noopener noreferrer"&gt;launchd&lt;/a&gt; 機制啟動 ollama 服務。首先，必須在 &lt;code&gt;~/Library/LaunchAgents/&lt;/code&gt; 建立一個&lt;code&gt;com.ollama.serve.plist&lt;/code&gt; 服務描述檔：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;plist&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Label&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;com.ollama.serve&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;ProgramArguments&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/Applications/Ollama.app/Contents/Resources/ollama&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;serve&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;EnvironmentVariables&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;OLLAMA_HOST&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;0.0.0.0:11434&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;RunAtLoad&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;KeepAlive&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;其中：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Label&lt;/strong&gt; 鍵：此服務的名稱。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ProgramArgs&lt;/strong&gt; 鍵：此服務要執行的指令。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EnvironmentVariables&lt;/strong&gt; 鍵：要提供給此服務執行時的環境變數&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;這個服務會在此帳號的使用者登入時啟動，要讓這個服務生效，必須先把已經在執行的 ollama 服務關閉：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;killall ollama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;然後使用 &lt;a href="https://ss64.com/mac/launchctl.html" rel="noopener noreferrer"&gt;launchctl&lt;/a&gt; 指令載入剛剛寫好的設定：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;launchctl load ~/Library/LaunchAgents/com.ollama.serve.plist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;載入後，就可以測試看看，先取得 IP：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ipconfig getifaddr en0
192.168.0.37
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;再利用 curl 工具測試：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://192.168.0.37:11434
Ollama is running
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;確認可以正常運作之後，還有最重要的一步，移除原本 ollama 桌面程式在登入後自動執行並啟動 ollama 服務的定，否則 launchd 啟動服務時會因為已經有在監聽本機迴路的 ollama 而失敗：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6nfiarrvfndikrn4uaa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6nfiarrvfndikrn4uaa.png" alt="圖片" width="716" height="239"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;移除 ollama 項目後，之後重新開機登入此帳號，就會自動啟動剛剛設定的服務了。&lt;/p&gt;

&lt;p&gt;之後若是有修改服務的設定檔，就要先從系統中卸載之前載入的設定檔：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;launchctl unload ~/Library/LaunchAgents/com.ollama.serve.plist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;再重新載入設定檔即可。&lt;/p&gt;

&lt;h2&gt;
  
  
  使用 ollama 指令連接遠端的 ollama 服務
&lt;/h2&gt;

&lt;p&gt;只要設定 &lt;code&gt;OLLAMA_HOST&lt;/code&gt; 環境變數為遠端 ollama 服務的位址，就可以連接遠端 ollama 服務，例如：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;沒有設定 &lt;code&gt;OLLAMA_HOST&lt;/code&gt; 時，這是本機上 ollama 安裝的模型：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME                                                   ID              SIZE      MODIFIED    
weitsung50110/llama-3-taiwan:8b-instruct-dpo-q4_K_M    7fcf06fa5eaa    4.9 GB    5 days ago     
weitsung50110/multilingual-e5-large-instruct:f16       ad6d1b04ec00    1.1 GB    2 weeks ago    
gemma3:latest                                          a2af6cc3eb7f    3.3 GB    2 weeks ago    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;我們可以先設定環境變數（以下以 Linux 示範），再重新執行同樣的指令：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;OLLAMA_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.0.37 ollama list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;現在看到的則是我在 192.168.0.37 位址的 ollama 安裝的模型：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME                                                   ID              SIZE      MODIFIED       
gemma3:4b                                              a2af6cc3eb7f    3.3 GB    38 minutes ago    
weitsung50110/multilingual-e5-large-instruct:f16       ad6d1b04ec00    1.1 GB    3 hours ago       
weitsung50110/llama-3-taiwan:8b-instruct-dpo-q4_K_M    7fcf06fa5eaa    4.9 GB    3 hours ago       
gemma3:12b                                             f4031aab637d    8.1 GB    24 hours ago      
gemma3:1b                                              8648f39daa8f    815 MB    24 hours ago      
Darrrrr/mymodel:latest                                 40a13e3b82e2    815 MB    12 days ago       
deepseek-r1:14b                                        ea35dfe18182    9.0 GB    12 days ago       
qwq:latest                                             009cb3f08d74    19 GB     2 weeks ago       
gemma3:27b                                             a418f5838eaf    17 GB     2 weeks ago       
deepseek-r1:70b                                        0c1615a8ca32    42 GB     2 weeks ago       
deepseek-r1:32b                                        38056bbcbb2d    19 GB     2 weeks ago    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;這樣一來，你就可以彈性的配置實際要跑 ollama 模型的機器，其他的機器則只要透過遠端連線就可以使用同一組模型了。如果需要，你也可以直接在系統或是 shell 的設定檔中設定環境變數，就不需要每次執行都要先設定環境變數了。&lt;/p&gt;

&lt;h2&gt;
  
  
  使用 API 連接遠端的 ollama
&lt;/h2&gt;

&lt;p&gt;從遠端利用 API 使用 ollama：只要透過 API 位址的參數指定遠端 IP 即可，本例遠端 ollama 服務位於 &lt;code&gt;192.168.0.37&lt;/code&gt;：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://192.168.0.37:11434/api/chat &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
&amp;gt;   "model": "gemma3:4b",
&amp;gt;   "messages": [
&amp;gt;     {
&amp;gt;       "role": "user",
&amp;gt;       "content": "你好"
&amp;gt;     }
&amp;gt;   ],
&amp;gt;   "stream": false
&amp;gt; }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;可以取得正確結果：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"model":"gemma3:4b","created_at":"2025-04-30T09:48:53.946791Z","message":{"role":"assistant","content":"你好！很高兴和你聊天。有什么我可以帮助你的吗？\n"},"done_reason":"stop","done":true,"total_duration":361840209,"load_duration":57624667,"prompt_eval_count":10,"prompt_eval_duration":79502667,"eval_count":15,"eval_duration":224293500}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;使用 ollama 套件則是指定 &lt;code&gt;host&lt;/code&gt; 參數：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;ollama&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AsyncClient&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AsyncClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;http://192.168.0.37:11434&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gemma3:4b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;你是誰?&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;回應:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;若要使用 OpenAI API，必須傳入遠端 ollama 伺服器的位址連同&lt;strong&gt;連接埠&lt;/strong&gt;（預設為 &lt;code&gt;11434&lt;/code&gt;）給 &lt;code&gt;base_url&lt;/code&gt; 參數：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="c1"&gt;# 配置遠端 Ollama API
&lt;/span&gt;&lt;span class="n"&gt;OLLAMA_API_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://192.168.0.37:11434/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# 遠端 Ollama 伺服器
# OLLAMA_API_URL = "http://127.0.0.1:11434/v1"  # 本機 Ollama 伺服器
&lt;/span&gt;&lt;span class="n"&gt;MODEL_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemma3:12b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# 初始化 OpenAI 客戶端，指向 Ollama 的 API
&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OLLAMA_API_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 發送聊天完成請求
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MODEL_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;你好&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# 提取回應內容
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ollama</category>
    </item>
    <item>
      <title>用 Inkscape 批次幫 SVG 檔文字轉外框</title>
      <dc:creator>codemee</dc:creator>
      <pubDate>Wed, 30 Jul 2025 09:55:24 +0000</pubDate>
      <link>https://dev.to/codemee/yong-inkscape-pi-ci-bang-svg-dang-wen-zi-zhuan-wai-kuang-c3n</link>
      <guid>https://dev.to/codemee/yong-inkscape-pi-ci-bang-svg-dang-wen-zi-zhuan-wai-kuang-c3n</guid>
      <description>&lt;p&gt;我的工作會遇到需要把 SVG 檔內含的文字轉外框，這可以透過開放原始碼的 &lt;a href="https://inkscape.org/" rel="noopener noreferrer"&gt;Inkscape&lt;/a&gt; 處理，而且 Inkscape 還提供 &lt;a href="https://inkscape.org/doc/inkscape-man.html" rel="noopener noreferrer"&gt;CLI 介面&lt;/a&gt;，可以像是透過 Selenium 或是 Playwright 操控瀏覽器那樣自動化。於是我就請 &lt;a href="https://grok.com/share/bGVnYWN5_c6cd1273-43db-4c8d-bc54-c6b69b34e8b3" rel="noopener noreferrer"&gt;Grok&lt;/a&gt; 幫我設計腳本，讓我可以批次處理一堆 SVG 檔轉外框在存檔的功能，以下是透過指令把 SVG 轉外框的批次檔：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;@echo &lt;span class="na"&gt;off&lt;/span&gt;
&lt;span class="c"&gt;REM batch_text_to_path.bat&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="vm"&gt;%%f&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;(*&lt;/span&gt;.svg&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="kd"&gt;Processing&lt;/span&gt; &lt;span class="vm"&gt;%%f&lt;/span&gt;...
    &lt;span class="s2"&gt;"C:\Program Files\Inkscape\bin\inkscape.exe"&lt;/span&gt; &lt;span class="na"&gt;--actions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"select-all;org.inkscape.text.convert_to_path;export-filename:&lt;/span&gt;&lt;span class="vm"&gt;%%~nf&lt;/span&gt;&lt;span class="s2"&gt;_converted.svg;export-do"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="vm"&gt;%%f&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;它會把目前資料夾下的所有 SVG 檔用 Inkscape 一一開啟，開啟後：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;選取所有物件&lt;/li&gt;
&lt;li&gt;文字轉外框&lt;/li&gt;
&lt;li&gt;以原檔名加上 "_converted" 字尾存檔&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;也有 bash 版：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# batch_text_to_path.sh&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;file &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.svg&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Processing &lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;
    inkscape &lt;span class="nt"&gt;--actions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"select-all;org.inkscape.text.convert_to_path;export-filename:&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="p"&gt;%.svg&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_converted.svg;export-do"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;或是 PowerShell 版：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# batch_text_to_path.ps1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$inkscapePath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:\Program Files\Inkscape\bin\inkscape.exe"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 根據你的 Inkscape 安裝路徑調整&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$svgFiles&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Get-ChildItem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Filter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*.&lt;/span&gt;&lt;span class="nf"&gt;svg&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="kr"&gt;foreach&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$svgFiles&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Processing &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Name&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$inkscapePath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--actions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"select-all;org.inkscape.text.convert_to_path;export-filename:&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BaseName&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;_converted.svg;export-do"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FullName&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Saved as &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BaseName&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;_converted.svg"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;如果想知道有哪些動作可以透過 CLI 完成，可以執行 &lt;code&gt;--action-list&lt;/code&gt;：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;c:\Program&lt;/span&gt;&lt;span class="se"&gt;` &lt;/span&gt;&lt;span class="nx"&gt;Files\Inkscape\bin\inkscape&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--action-list&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>inkscape</category>
      <category>svg</category>
    </item>
    <item>
      <title>macOS 上 #! 的寫法</title>
      <dc:creator>codemee</dc:creator>
      <pubDate>Fri, 18 Jul 2025 06:09:26 +0000</pubDate>
      <link>https://dev.to/codemee/macos-shang-de-xie-fa-3nog</link>
      <guid>https://dev.to/codemee/macos-shang-de-xie-fa-3nog</guid>
      <description>&lt;p&gt;今天才注意到 macOS 上的 hashbang（也稱 shebang） 寫法有點奇特，會長得像是這樣：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#! /usr/bin/env python3&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;才發現自己跟 shell script 一點都不熟，首先 hashbang 要寫用來執行腳本的執行檔&lt;strong&gt;完整路徑&lt;/strong&gt;，由於是完整路徑，如果遇到環境不同，執行檔路徑不一樣的系統，同一個腳本就可能會找不到執行檔而無法執行。為了解決這個問題， 就有一個特別的執行檔，也就是剛剛看到的 &lt;code&gt;/usr/bin/env&lt;/code&gt;，單獨執行它會顯示所有的環境變數，像是這樣：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ env
USER=meebox
LOGNAME=meebox
HOME=/Users/meebox
PATH=/Users/meebox/.nvm/versions/node/v24.4.0/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/homebrew/bin
SHELL=/bin/zsh
...
LANG=zh_TW.UTF-8
LC_ALL=zh_TW.UTF-8
_=/usr/bin/env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;如果加上額外的引數，它就會依據 &lt;code&gt;PATH&lt;/code&gt; 環境變數去找該引數指定的執行檔，所以剛剛看到的那一行：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#! /usr/bin/env python3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;就可以在不需要寫出 &lt;code&gt;python3&lt;/code&gt; 絕對路徑的前提下，自動找到並以 &lt;code&gt;python3&lt;/code&gt; 來執行腳本了。而且這個 &lt;code&gt;/usr/bin/env&lt;/code&gt; 也不是 macOS 才有，現代的 Linux 發行版本預設也幾乎都會安裝這個屬於 &lt;code&gt;coreutils&lt;/code&gt; 套件的 &lt;a href="https://man7.org/linux/man-pages/man1/env.1.html" rel="noopener noreferrer"&gt;&lt;code&gt;env&lt;/code&gt;&lt;/a&gt; 工具程式。&lt;/p&gt;

</description>
      <category>shell</category>
    </item>
    <item>
      <title>讓 MicroPython 輸入中文</title>
      <dc:creator>codemee</dc:creator>
      <pubDate>Sat, 05 Jul 2025 07:30:51 +0000</pubDate>
      <link>https://dev.to/codemee/rang-micropython-shu-ru-zhong-wen-58gn</link>
      <guid>https://dev.to/codemee/rang-micropython-shu-ru-zhong-wen-58gn</guid>
      <description>&lt;p&gt;MicroPython 不知道為了什麼原因，在實作的時候 &lt;code&gt;input&lt;/code&gt; 內建函式&lt;a href="https://github.com/micropython/micropython/issues/7585" rel="noopener noreferrer"&gt;只能接受 ASCII 字元&lt;/a&gt;，例如：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;請輸入：&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;請輸入&lt;/span&gt;&lt;span class="err"&gt;：&lt;/span&gt;&lt;span class="n"&gt;你好&lt;/span&gt;
&lt;span class="n"&gt;WARNING&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MicroPython&lt;/span&gt; &lt;span class="n"&gt;ignores&lt;/span&gt; &lt;span class="n"&gt;non&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;ascii&lt;/span&gt; &lt;span class="n"&gt;characters&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;就會看到雖然好像輸入完成，但實際上印出輸入的文字時只會得到空字串。由於 &lt;code&gt;input&lt;/code&gt; 不接受非 ASCII 字元，所以它 echo 回去的就是空字串， 在 Thonny 環境下會檢查 echo 回來的內容跟輸入內容是否相同，如果不相同，而且輸入內容含有非 ASCII 字元，就會&lt;a href="https://github.com/thonny/thonny/blob/a6b2c4979c6cfd29bffd5e7b87c521b29605781d/thonny/plugins/micropython/mp_back.py#L487" rel="noopener noreferrer"&gt;顯示警告訊息&lt;/a&gt;，告知 MicroPython 的 &lt;code&gt;input&lt;/code&gt; 不接受非 ASCII 字元。&lt;/p&gt;

&lt;p&gt;好在如果直接使用 &lt;code&gt;sys.stdin&lt;/code&gt; 取得的串流物件，就可以輸入中文了：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;你好&lt;/span&gt;
&lt;span class="n"&gt;WARNING&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MicroPython&lt;/span&gt; &lt;span class="n"&gt;ignores&lt;/span&gt; &lt;span class="n"&gt;non&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;ascii&lt;/span&gt; &lt;span class="n"&gt;characters&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;你好&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;在互動窗格測試時，還是會看到警告訊息，這是因為我們沒有在收到輸入後 echo 回去，所以 Thonny 比對到的 echo 內容與輸入內容仍然不同，因此噴出警告訊息。只要將輸入內容原封不動 echo 回去，就不會看到警告訊息了：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;你好&lt;/span&gt;
&lt;span class="mi"&gt;7&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;你好&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;我是誰&lt;/span&gt;
&lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;我是誰&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;其中顯示的數字是 &lt;code&gt;write&lt;/code&gt; 傳回的輸出字元數。因此，我們就可以利用這個方式撰寫客製版本的 &lt;code&gt;input&lt;/code&gt; 函式了：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;select&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;u_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;# 顯示提示
&lt;/span&gt;    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# 讀取輸入
&lt;/span&gt;    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;u_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;gt; &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;實際測試都可以正常輸入中文：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; %Run -c $EDITOR_CONTENT

MPY: soft reboot
&amp;gt; 你好
你好
&amp;gt; 

&amp;gt; 我是誰
我是誰
&amp;gt; 

&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;不過似乎都會多出換行字元，導致下一輪輸入時會直接被當成使用者已經按下了 Enter，底下加上接收輸入前先把輸入的暫存區清空的步驟：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;select&lt;/span&gt;

&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;poll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;     &lt;span class="c1"&gt;# 建立偵測物件
&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;# 偵測標準輸入
&lt;/span&gt;    &lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;POLLIN&lt;/span&gt;     &lt;span class="c1"&gt;# 偵測是否有資料待讀取
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;u_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;poll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;            &lt;span class="c1"&gt;# 有資料待讀取
&lt;/span&gt;        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# 先清空已輸入資料 
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;# 顯示提示
&lt;/span&gt;    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# 讀取輸入
&lt;/span&gt;    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;u_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;gt; &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;這樣就一切正常了：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; %Run -c $EDITOR_CONTENT

MPY: soft reboot
&amp;gt; 你好
你好
&amp;gt; 我是誰
我是誰
&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>micropython</category>
      <category>thonny</category>
    </item>
    <item>
      <title>IPython 的奇特 feature</title>
      <dc:creator>codemee</dc:creator>
      <pubDate>Thu, 24 Apr 2025 13:11:13 +0000</pubDate>
      <link>https://dev.to/codemee/ipython-de-qi-te-feature-2fn8</link>
      <guid>https://dev.to/codemee/ipython-de-qi-te-feature-2fn8</guid>
      <description>&lt;p&gt;下午在 Colab 被一個奇妙的問題卡了好久，我把問題簡化成底下這個儲存格：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;IPython.display&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Markdown&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sample_data&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;只要一執行，就會看到錯誤訊息：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---------------------------------------------------------------------------
IsADirectoryError                         Traceback (most recent call last)
&amp;lt;ipython-input-1-3e6438a6a511&amp;gt; in &amp;lt;cell line: 0&amp;gt;()
      1 from IPython.display import Markdown
----&amp;gt; 2 m = Markdown('sample_data')

1 frames
/usr/local/lib/python3.11/dist-packages/IPython/core/display.py in reload(self)
    660         """Reload the raw data from file or URL."""
    661         if self.filename is not None:
--&amp;gt; 662             with open(self.filename, self._read_flags) as f:
    663                 self.data = f.read()
    664         elif self.url is not None:

IsADirectoryError: [Errno 21] Is a directory: 'sample_data'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;從錯誤訊息就可以猜出來，它把我要以 Markdown 格式解譯的 "sample_data" 字串內容當成路徑名稱解譯，好死不死，Colab 預設就有一個名稱為 "sample_data" 的資料夾，正因為它是資料夾，所以當 IPython 底層的程式碼想要把它當成檔案讀取時，就會發生你看到的錯誤。&lt;/p&gt;

&lt;p&gt;但為什麼為這樣？&lt;/p&gt;

&lt;h2&gt;
  
  
  DisplayObject 預設會從檔案更新內容
&lt;/h2&gt;

&lt;p&gt;之所以會發生剛剛看到的問題，就是因為 &lt;a href="https://ipython.readthedocs.io/en/stable/api/generated/IPython.display.html#" rel="noopener noreferrer"&gt;&lt;code&gt;IPython.display&lt;/code&gt;&lt;/a&gt; 模組中的 &lt;a href="https://ipython.readthedocs.io/en/stable/api/generated/IPython.display.html#IPython.display.Markdown" rel="noopener noreferrer"&gt;&lt;code&gt;Markdown&lt;/code&gt;&lt;/a&gt; 等格式化顯示物件都是 &lt;a href="https://ipython.readthedocs.io/en/stable/api/generated/IPython.display.html#IPython.display.DisplayObject" rel="noopener noreferrer"&gt;&lt;code&gt;DisplayObject&lt;/code&gt;&lt;/a&gt; 類別的子類別，這個類別的 &lt;a href="https://github.com/ipython/ipython/blob/aa25535d3765641e31f1d218537540e41b6f1a74/IPython/core/display.py#L297" rel="noopener noreferrer"&gt;&lt;code&gt;__init__&lt;/code&gt;&lt;/a&gt; 是這樣的（已刪除註解）：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PurePath&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;http&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
                &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
                &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nf"&gt;_safe_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
                &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
                &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_check_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;你會看到它做幾件事：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;如果 &lt;code&gt;data&lt;/code&gt; 參數是路徑類的物件，就先轉成字串。&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如果 &lt;code&gt;data&lt;/code&gt; 是字串，就會先判斷是不是網址，如果是網址且沒有傳入網址給 &lt;code&gt;url&lt;/code&gt;（預設就為 &lt;code&gt;None&lt;/code&gt;），就設定網址給 &lt;code&gt;url&lt;/code&gt;；若不是網址，而且沒有傳入檔案路徑給 &lt;code&gt;filename&lt;/code&gt;（預設就是 &lt;code&gt;None&lt;/code&gt;），會依照底下的 &lt;a href="https://github.com/ipython/ipython/blob/aa25535d3765641e31f1d218537540e41b6f1a74/IPython/core/display.py#L56" rel="noopener noreferrer"&gt;&lt;code&gt;safe_exists&lt;/code&gt;&lt;/a&gt; 函式結果設定給 &lt;code&gt;filename&lt;/code&gt;：&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_safe_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Check path, but don&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t let exceptions raise&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;這個函式很簡單，就是檢查輸入的內容是不是一個合法的路徑，不過請注意，它只檢查路徑是否存在，但並不會管這個路徑是檔案還是資料夾。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;最後會叫用 &lt;code&gt;self.reload&lt;/code&gt; 嘗試從網址或是檔案讀取更新內容：&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Reload the raw data from file or URL.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;encoding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_read_flags&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_read_flags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Deferred import
&lt;/span&gt;        &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;urllib.request&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;urlopen&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="err"&gt;（&lt;/span&gt;&lt;span class="n"&gt;略&lt;/span&gt;&lt;span class="err"&gt;）&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;就是這裡導致我遇到的問題，由於它會在 &lt;code&gt;data&lt;/code&gt; 不是網址而且沒有傳入檔名給 &lt;br&gt;
&lt;code&gt;filename&lt;/code&gt; 參數時把 &lt;code&gt;data&lt;/code&gt; 指派給 &lt;code&gt;filename&lt;/code&gt;，所以在 &lt;code&gt;reload&lt;/code&gt; 方法中就會嘗試去讀取檔案內容，並因為 "sample_data" 是資料夾而發生錯誤。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  你的 feature 是我的 bug
&lt;/h2&gt;

&lt;p&gt;我推想 IPython 這樣的設計，應該是想增加彈性，只要透過 &lt;code&gt;data&lt;/code&gt; 參數，就可以依據需要傳單純的內容，或者是傳入可以載入內容的網址或檔案路徑，因為在 IPython 的文件上，&lt;a href="https://ipython.readthedocs.io/en/stable/api/generated/IPython.display.html#IPython.display.DisplayObject" rel="noopener noreferrer"&gt;&lt;code&gt;data&lt;/code&gt;&lt;/a&gt; 參數就是多用途的：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;data (unicode, str or bytes) – The raw data or a URL or file to load the data from&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;所以這應該是個 feature，可是我認為你都另外獨立有 &lt;code&gt;url&lt;/code&gt;、&lt;code&gt;filename&lt;/code&gt; 參數了，這個彈性只是會增加意外的驚嚇！&lt;/p&gt;

&lt;p&gt;目前唯一的解法，就是在建立這些 &lt;code&gt;DisplayObject&lt;/code&gt; 家族的物件時，必須自己檢查傳入的字串會不會剛好是某個檔案或是資料夾的路徑，如果是，就要自己用其他方式避開，例如變成 inline code：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;`sample_data`&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;就不會有事，或者是在字串開頭隨意加個空白字元之類的，總之，這錯誤就是要在剛好的狀況下才會發生，但突然遇到就會覺得真是怪，好特別的 feature。&lt;/p&gt;

&lt;p&gt;對了，由於這是 IPython 的問題，所以使用 Jupyter 也會遇到類似的狀況。&lt;/p&gt;

</description>
      <category>python</category>
      <category>colab</category>
      <category>jupyter</category>
    </item>
  </channel>
</rss>
