

<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Python筆記 &#8211; Max的程式語言筆記</title>
	<atom:link href="https://stackoverflow.max-everyday.com/category/python/feed/" rel="self" type="application/rss+xml" />
	<link>https://stackoverflow.max-everyday.com</link>
	<description>我要當一個豬頭，快樂過每一天</description>
	<lastBuildDate>Tue, 31 Mar 2026 05:02:59 +0000</lastBuildDate>
	<language>zh-TW</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://stackoverflow.max-everyday.com/wp-content/uploads/2017/02/max-stackoverflow-256.png</url>
	<title>Python筆記 &#8211; Max的程式語言筆記</title>
	<link>https://stackoverflow.max-everyday.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>用 AI 修改原作者 theme改版</title>
		<link>https://stackoverflow.max-everyday.com/2026/03/patch_gutenshop-py/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/03/patch_gutenshop-py/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 05:02:58 +0000</pubDate>
				<category><![CDATA[Python筆記]]></category>
		<category><![CDATA[WordPress筆記]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=8211</guid>

					<description><![CDATA[希望可以把改動的部份寫成一個 python sc...]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="558" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/WindowsTerminal_2026-03-31-13-02-4g-1024x558.jpg" alt="" class="wp-image-8212" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/WindowsTerminal_2026-03-31-13-02-4g-1024x558.jpg?v=1774933354 1024w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/WindowsTerminal_2026-03-31-13-02-4g-600x327.jpg?v=1774933354 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/WindowsTerminal_2026-03-31-13-02-4g-768x419.jpg?v=1774933354 768w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/WindowsTerminal_2026-03-31-13-02-4g-1536x837.jpg?v=1774933354 1536w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/WindowsTerminal_2026-03-31-13-02-4g.jpg?v=1774933354 1970w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>希望可以把改動的部份寫成一個 python script 給我進行 patch.</p>



<p>目前的設定是 max-width: 75rem; (1200px)，若扣除內距或特定的瀏覽器渲染，體感寬度確實接近 1150px。要提升到1280px，我們需要將其改為 80rem (1280 / 16 = 780)。</p>



<p>這是一個進階版的 Python 腳本，它會自動掃描伺服器路徑（如 /var/www/），尋找所有名為 gutenshop 的主題目錄，並統一對其<br>foundation.css 進行寬度補丁。<br><br>✦ 我現在就在當前目錄為您產生 patch_gutenshop.py 實體檔案</p>



<pre class="wp-block-code"><code>import os
import re
import sys

def patch_gutenshop_width(base_path='.'):
    """
    自動尋找並修改所有 gutenshop 主題的寬度限制。
    目標寬度: 1280px (80rem)
    """
    # 目標檔案在主題內的相對路徑
    target_rel_path = os.path.join('css', 'foundation.css')
    found_count = 0
    patched_count = 0

    print(f"開始掃描目錄: {os.path.abspath(base_path)}")
    print("-" * 50)

    # 遍歷目錄尋找所有名為 gutenshop 的主題目錄
    for root, dirs, files in os.walk(base_path):
        if os.path.basename(root) == 'gutenshop':
            full_file_path = os.path.join(root, target_rel_path)
            
            if os.path.exists(full_file_path):
                found_count += 1
                print(f"找到目標: {full_file_path}")
                
                try:
                    with open(full_file_path, 'r', encoding='utf-8') as f:
                        content = f.read()

                    # 將 75rem (1200px) 替換為 80rem (1280px)
                    # 使用正則表達式鎖定 max-width: 75rem
                    new_content = re.sub(r'max-width:\s*75rem', 'max-width: 80rem', content)

                    if content == new_content:
                        # 檢查是否已經是 80rem，避免誤報
                        if 'max-width: 80rem' in content:
                            print("  &#91;跳過] 寬度已經是 1280px (80rem)")
                        else:
                            print("  &#91;跳過] 檔案中未找到 max-width: 75rem 設定")
                    else:
                        with open(full_file_path, 'w', encoding='utf-8') as f:
                            f.write(new_content)
                        patched_count += 1
                        print("  &#91;成功] 已將寬度修正為 1280px (80rem)")
                
                except Exception as e:
                    print(f"  &#91;錯誤] 無法讀寫檔案: {e}")
            
    print("-" * 50)
    print(f"掃描結束。共找到 {found_count} 個主題，成功補丁 {patched_count} 個檔案。")

if __name__ == "__main__":
    # 如果執行時有帶參數，則以參數為搜尋路徑，否則預設為當前路徑 '.'
    search_dir = sys.argv&#91;1] if len(sys.argv) > 1 else '.'
    
    # Linux 權限提示
    if os.name != 'nt' and hasattr(os, 'getuid') and os.getuid() != 0:
        print("提示：在 Linux 伺服器上建議使用 sudo 權限執行以確保檔案可寫入。")
        
    patch_gutenshop_width(search_dir)
</code></pre>



<p>使用方式：</p>



<p>本機測試：直接執行 python patch_gutenshop.py，它會掃描當前目錄。</p>



<p>伺服器大量修改：將此檔案上傳至伺服器，並指定掃描路徑：</p>



<pre class="wp-block-code"><code>sudo python3 patch_gutenshop.py /var/www </code></pre>



<p>此腳本會尋找所有路徑下包含 gutenshop 的目錄，並修改其 css/foundation.css 中的 max-width: 75rem 為 max-width: 80rem (1280px)。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/03/patch_gutenshop-py/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>為什麼別台電腦使用 python 3.11 打包的pypi 程式, 在我這台 win11 + python 3.14 透過 pip -m install 安裝時會出問題? 如何避免其他人安裝失敗?</title>
		<link>https://stackoverflow.max-everyday.com/2026/03/python-3-11-pypi-failed-on-3-14/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/03/python-3-11-pypi-failed-on-3-14/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Mon, 30 Mar 2026 10:35:22 +0000</pubDate>
				<category><![CDATA[Python筆記]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=8195</guid>

					<description><![CDATA[﻿◐ Now I have a good und...]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="491" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/WindowsTerminal_2026-03-30-09-55-4e-1024x491.jpg?v=1774835799" alt="" class="wp-image-8196" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/WindowsTerminal_2026-03-30-09-55-4e-1024x491.jpg?v=1774835799 1024w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/WindowsTerminal_2026-03-30-09-55-4e-600x288.jpg?v=1774835799 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/WindowsTerminal_2026-03-30-09-55-4e-768x368.jpg?v=1774835799 768w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/WindowsTerminal_2026-03-30-09-55-4e-1536x736.jpg?v=1774835799 1536w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/WindowsTerminal_2026-03-30-09-55-4e-2048x982.jpg?v=1774835799 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>﻿◐ Now I have a good understanding of the codebase. Let me analyze the problem:</p>



<ol class="wp-block-list">
<li>The package is built with Python 3.10 (CI/CD in publish.yml uses <code>python-version: '3.10'</code>)</li>



<li>The <code>requires-python = ">=3.10"</code> in pyproject.toml is set correctly</li>



<li>The user says &#8220;別台電腦使用 python 3.11 打包的pypi 程式&#8221; &#8211; but actually looking at the CI, it builds with Python 3.10, not 3.11 The real question is: why does a PyPI package built with Python 3.11 (or 3.10) fail when installed on Python 3.14? The main culprits are likely the wheel format and Python version compatibility. If the package is distributed as a version-specific wheel (like cp311), it won&#8217;t work on Python 3.14 unless there&#8217;s also a universal wheel or source<br>distribution available. Even though <code>requires-python = ">=3.10"</code> should theoretically allow Python 3.14, the actual wheel files need to support that version. I should check what the user&#8217;s build output shows to see which wheel formats<br>are being published. The package type determines compatibility—pure Python wheels tagged <code>py3-none-any</code> work across Python versions, while CPython-specific wheels only work on their exact version, and source distributions get built<br>during installation. Since this project uses <code>python -m build</code> with pure Python code, it should generate a universal wheel, so version mismatches shouldn&#8217;t be the issue. The real concern is whether dependencies themselves support<br>Python 3.14, which could cause installation failures even if the main package is compatible. Looking at the remaining issues, I need to set up a comprehensive testing strategy across Python versions 3.10 through 3.13, align the<br>requirements.txt with what&#8217;s actually optional in pyproject.toml, and tighten the dependency constraints to prevent future breakage. I should also add Python version classifiers and create a CI workflow that catches compatibility<br>issues early.</li>
</ol>



<p>● 以下是所有修改：</p>



<p>增加 .github/workflows/ci.yml‎</p>



<p> &#8211; push / PR 時自動在 Python<br>  3.10、3.11、3.12、3.13 × Ubuntu + Windows 共 8 種環境跑 smoke test<br> &#8211; 確保發布前已驗證多版本相容性</p>



<pre class="wp-block-code"><code>name: CI

on:
  push:
    branches: &#91;main]
  pull_request:
    branches: &#91;main]

jobs:
  test:
    name: Python ${{ matrix.python-version }} on ${{ matrix.os }}
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        python-version: &#91;"3.10", "3.11", "3.12", "3.13"]
        os: &#91;ubuntu-latest, windows-latest]

    steps:
      - uses: actions/checkout@v4

      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}

      - name: Install package
        run: pip install .

      - name: Smoke test — CLI help
        run: blogpro --help

      - name: Smoke test — versions command
        run: blogpro versions
</code></pre>



<p>根本原因補充：你這次安裝其實成功了，只是 PATH 問題。Python 3.14 是 pre-release，依賴套件（尤其是 ddgs）可能尚未支援，這才是真正的風險點。現在 ddgs 已改為 optional，不會再造成硬性安裝失敗。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<pre class="wp-block-code"><code>修改內容

requirements.txt

 - openai>=1.0.0 → openai>=2.0.0
 - ddgs>=0.1 改為註解（optional，避免 Python
  3.14 上安裝失敗）

pyproject.toml

 - openai>=1.0.0 → openai>=2.0.0（避免安裝
  1.x 後執行時 API 錯誤）
 - 新增 classifiers，宣告支援 Python
  3.10 / 3.11 / 3.12 / 3.13（PyPI 頁面會顯示）
</code></pre>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/03/python-3-11-pypi-failed-on-3-14/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>在 GitHub 建立一個 &#8220;Release&#8221;，GitHub 就會自動幫你發佈到 PyPI</title>
		<link>https://stackoverflow.max-everyday.com/2026/03/github-release-to-pypi/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/03/github-release-to-pypi/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Sat, 28 Mar 2026 21:40:19 +0000</pubDate>
				<category><![CDATA[Python筆記]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=8181</guid>

					<description><![CDATA[採用 Trusted Publishing 最大...]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img decoding="async" width="1016" height="896" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/2026-03-29_05-34_my.jpg?v=1774733732" alt="" class="wp-image-8182" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/2026-03-29_05-34_my.jpg?v=1774733732 1016w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/2026-03-29_05-34_my-600x529.jpg?v=1774733732 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/2026-03-29_05-34_my-768x677.jpg?v=1774733732 768w" sizes="(max-width: 1016px) 100vw, 1016px" /></figure>



<p>採用 Trusted Publishing 最大的好處就是 安全性高且不需要手動管理密碼或 Token。</p>



<p>要完成這項設定，我們需要分兩步進行：</p>



<ol class="wp-block-list">
<li>在你的專案中建立 GitHub Action 設定檔（這部分我可以幫你做）。</li>



<li>在 PyPI 官網設定「信任」你的 GitHub 專案（這部分需要你手動操作一次）。</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>第一步：建立 GitHub Action 設定檔</p>



<p>我將為你建立 <code>.github/workflows/publish.yml</code>。這個腳本會在你在 GitHub 上建立新的<br>&#8220;Release&#8221;（發佈版本）時，自動執行建置並上傳到 PyPI。</p>



<p>我現在就幫你建立這個檔案(publish.yml)。</p>



<pre class="wp-block-code"><code>name: Publish to PyPI

on:
  release:
    types: &#91;published]

jobs:
  build-n-publish:
    name: Build and publish to PyPI
    runs-on: ubuntu-latest
    permissions:
      # 這是在 Trusted Publishing 中取得 PyPI ID Token 的必要權限
      id-token: write
      contents: read

    steps:
    - uses: actions/checkout@v4
    
    - name: Set up Python
      uses: actions/setup-python@v5
      with:
        python-version: '3.10'

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install build

    - name: Build sdist and wheel
      run: python -m build

    - name: Publish to PyPI
      uses: pypa/gh-action-pypi-publish@release/v1
</code></pre>



<p>✦ 第二步：在 PyPI 官網設定「信任」你的 GitHub 專案</p>



<p>這部分我無法自動幫你做，因為它需要你在瀏覽器中登入 PyPI 官網。請跟著以下簡單的步驟：</p>



<ol class="wp-block-list">
<li>登入 PyPI 官網 (https://pypi.org/manage/account/publishing/)。</li>



<li>找到 &#8220;Trusted Publishing&#8221; 區段，點擊 &#8220;Add a new publisher&#8221; 並選擇 &#8220;GitHub&#8221;。</li>



<li>填入以下資訊：
<ul class="wp-block-list">
<li>GitHub Repository Owner: max32002 (這是你的 GitHub 帳號)。</li>



<li>Repository Name: blog-pro-max (這是你的專案名稱)。</li>



<li>Workflow Name: publish.yml (這是我們剛才建立的檔名)。</li>



<li>Environment Name: (可以留空)。</li>
</ul>
</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">未來如何更新到 PyPI？</h2>



<p>只要你完成上面的一次性設定，以後要更新 PyPI，你只需要：</p>



<ol class="wp-block-list">
<li>在 GitHub 專案首頁點擊 &#8220;Releases&#8221;。</li>



<li>點擊 &#8220;Create a new release&#8221;。</li>



<li>設定一個 Tag（例如 v1.0.3），然後點擊 &#8220;Publish release&#8221;。 剩下的事 GitHub 就會自動幫你完成上傳到 PyPI 了！</li>
</ol>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/03/github-release-to-pypi/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Python MySQL to MSSQL 資料匯出</title>
		<link>https://stackoverflow.max-everyday.com/2026/03/python-mysql-to-mssql-export/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/03/python-mysql-to-mssql-export/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Mon, 16 Mar 2026 01:58:19 +0000</pubDate>
				<category><![CDATA[Python筆記]]></category>
		<category><![CDATA[mssql]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7960</guid>

					<description><![CDATA[mysql 使用 mysqldump 產生的 ....]]></description>
										<content:encoded><![CDATA[
<p>mysql 使用 mysqldump 產生的 .sql 檔案, 要匯入到 mssql 之中, 由於匯出的資料量太大, 直接轉換 mysql sql command 為  mssql sql command, 如果使用 SSMS(SQL Server Management Studio) 會遇到記憶體不足的問題.</p>



<p>透過 sqlcmd 匯入資料庫 (不經過 SSMS):</p>



<pre class="wp-block-code"><code>sqlcmd -S localhost -d %db_name% -E -i %output_file%</code></pre>



<p>這個也會遇到很多奇奇怪怪的問題, 明明在 SSMS 執行正常的 table, 在 sqlcmd 會遇到重覆插入 PK 值.</p>



<p>最佳解法是透過下列的python script 進行 export, 這是整合了「逐行讀取」、「自動切分 1000 筆」、「停用約束」以及修正後語法的完整版本：</p>



<pre class="wp-block-code"><code>import re
import pyodbc
import argparse
import sys

def parse_value(val_str):
    """Parse a single SQL value string and return a Python value."""
    val_str = val_str.strip()
    if val_str.upper() == 'NULL':
        return None
    if (val_str.startswith("'") and val_str.endswith("'")):
        # Remove surrounding quotes
        inner = val_str&#91;1:-1]
        # Unescape MySQL-style escape sequences
        result = &#91;]
        i = 0
        while i &lt; len(inner):
            if inner&#91;i] == '\\' and i + 1 &lt; len(inner):
                next_char = inner&#91;i + 1]
                if next_char == "'":
                    result.append("'")
                elif next_char == "\\":
                    result.append("\\")
                elif next_char == "n":
                    result.append("\n")
                elif next_char == "r":
                    result.append("\r")
                elif next_char == "t":
                    result.append("\t")
                elif next_char == "0":
                    result.append("\0")
                elif next_char == "%":
                    result.append("%")
                elif next_char == "_":
                    result.append("_")
                else:
                    result.append(next_char)
                i += 2
            elif inner&#91;i] == "'" and i + 1 &lt; len(inner) and inner&#91;i + 1] == "'":
                # SQL-style escaped quote
                result.append("'")
                i += 2
            else:
                result.append(inner&#91;i])
                i += 1
        return "".join(result)
    # Try numeric
    try:
        if '.' in val_str:
            return float(val_str)
        return int(val_str)
    except ValueError:
        return val_str

def split_row_values(row_str):
    """Split a single row '(val1, val2, ...)' into individual values."""
    # Remove outer parentheses
    inner = row_str.strip()
    if inner.startswith('('):
        inner = inner&#91;1:]
    if inner.endswith(')'):
        inner = inner&#91;:-1]
    
    values = &#91;]
    current = &#91;]
    in_string = False
    i = 0
    
    while i &lt; len(inner):
        char = inner&#91;i]
        
        if in_string:
            if char == '\\' and i + 1 &lt; len(inner):
                current.append(char)
                current.append(inner&#91;i + 1])
                i += 2
                continue
            elif char == "'":
                # Check for escaped quote ''
                if i + 1 &lt; len(inner) and inner&#91;i + 1] == "'":
                    current.append(char)
                    current.append(inner&#91;i + 1])
                    i += 2
                    continue
                else:
                    in_string = False
                    current.append(char)
            else:
                current.append(char)
        else:
            if char == "'":
                in_string = True
                current.append(char)
            elif char == ',':
                values.append("".join(current).strip())
                current = &#91;]
            else:
                current.append(char)
        i += 1
    
    if current:
        values.append("".join(current).strip())
    
    return values

def split_values_robust(values_str):
    """Split VALUES (...),(...),... into individual row strings."""
    rows = &#91;]
    buffer = &#91;]
    paren_depth = 0
    in_string = False
    i = 0
    length = len(values_str)
    
    while i &lt; length:
        char = values_str&#91;i]
        
        if in_string:
            if char == "\\" and i + 1 &lt; length:
                buffer.append(char)
                buffer.append(values_str&#91;i + 1])
                i += 2
                continue
            elif char == "'":
                # Check for '' escape
                if i + 1 &lt; length and values_str&#91;i + 1] == "'":
                    buffer.append(char)
                    buffer.append(values_str&#91;i + 1])
                    i += 2
                    continue
                in_string = False
                buffer.append(char)
            else:
                buffer.append(char)
        else:
            if char == "'":
                in_string = True
                buffer.append(char)
            elif char == "(":
                paren_depth += 1
                buffer.append(char)
            elif char == ")":
                paren_depth -= 1
                buffer.append(char)
                if paren_depth == 0:
                    rows.append("".join(buffer).strip())
                    buffer = &#91;]
            elif char == "," and paren_depth == 0:
                pass
            else:
                if paren_depth > 0:
                    buffer.append(char)
        i += 1
    return rows

def run_import(input_file):
    # 資料庫連線配置
    conn_config = {
        "DRIVER": "{ODBC Driver 18 for SQL Server}",
        "SERVER": "127.0.0.1",
        "DATABASE": "你的資料庫名稱",
        "UID": "帳號",
        "PWD": "密碼",
        "Encrypt": "yes",
        "TrustServerCertificate": "yes"
    }

    conn_str = ";".join(&#91;f"{k}={v}" for k, v in conn_config.items()])

    try:
        conn = pyodbc.connect(conn_str, autocommit=False)
        cursor = conn.cursor()
        print(f"檔案讀取中: {input_file}")
    except Exception as e:
        print(f"連線失敗: {e}")
        return

    try:
        with open(input_file, 'r', encoding='utf-8') as f:
            sql_content = f.read()
    except Exception as e:
        print(f"讀檔失敗: {e}")
        return

    # Handle INSERT INTO with parameterized queries
    insert_pattern = re.compile(
        r"INSERT INTO\s+`?(&#91;\w_]+)`?\s*(?:\((.*?)\))?\s*VALUES\s*(.+?);",
        re.S | re.I
    )

    truncated_tables = set()  # Track tables already truncated
    table_stats = {}  # Track cumulative success/error counts per table

    for match in insert_pattern.finditer(sql_content):
        table_name = match.group(1)
        cols_raw = match.group(2) if match.group(2) else ""
        raw_values = match.group(3)

        # Build column clause
        if cols_raw:
            col_names = &#91;c.strip().replace('`', '') for c in cols_raw.split(',')]
            columns_clause = "(&#91;" + "],&#91;".join(col_names) + "])"
        else:
            # No column list in SQL dump — fetch from MSSQL metadata
            # This is required when IDENTITY_INSERT is ON
            try:
                cursor.execute("""
                    SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
                    WHERE TABLE_NAME = ?
                    ORDER BY ORDINAL_POSITION
                """, table_name)
                db_cols = &#91;row&#91;0] for row in cursor.fetchall()]
                if db_cols:
                    columns_clause = "(&#91;" + "],&#91;".join(db_cols) + "])"
                else:
                    columns_clause = ""
            except:
                columns_clause = ""

        print(f"正在處理: {table_name}")

        # Truncate table before inserting (only once per table)
        if table_name not in truncated_tables:
            try:
                cursor.execute(f"TRUNCATE TABLE &#91;{table_name}]")
                conn.commit()
                print(f"  已清空資料表: {table_name}")
            except Exception as e:
                conn.rollback()
                # TRUNCATE fails if there are foreign key constraints, fallback to DELETE
                try:
                    cursor.execute(f"DELETE FROM &#91;{table_name}]")
                    conn.commit()
                    print(f"  已清空資料表 (DELETE): {table_name}")
                except Exception as e2:
                    conn.rollback()
                    print(f"  清空資料表失敗: {table_name}: {e2}")
            truncated_tables.add(table_name)

        all_rows = split_values_robust(raw_values)
        print(f"  共 {len(all_rows)} 筆資料")

        success_count = 0
        error_count = 0

        # Check if table has IDENTITY column, if so enable IDENTITY_INSERT
        has_identity = False
        try:
            cursor.execute(f"""
                SELECT COUNT(*) FROM sys.identity_columns 
                WHERE OBJECT_NAME(object_id) = ?
            """, table_name)
            row = cursor.fetchone()
            if row and row&#91;0] > 0:
                has_identity = True
        except:
            pass

        if has_identity:
            try:
                cursor.execute(f"SET IDENTITY_INSERT &#91;{table_name}] ON")
            except Exception as e:
                print(f"  無法開啟 IDENTITY_INSERT: {e}")

        for idx, row_str in enumerate(all_rows):
            raw_vals = split_row_values(row_str)
            parsed_vals = &#91;parse_value(v) for v in raw_vals]
            
            placeholders = ",".join(&#91;"?" for _ in parsed_vals])
            sql = f"INSERT INTO &#91;{table_name}] {columns_clause} VALUES ({placeholders})"
            
            try:
                cursor.execute(sql, parsed_vals)
                conn.commit()
                success_count += 1
            except Exception as e:
                conn.rollback()
                error_count += 1
                if error_count &lt;= 3:
                    print(f"  跳過錯誤列 {idx}: {e}")
                    # Print the values for debugging
                    preview_vals = &#91;str(v)&#91;:50] if v is not None else 'NULL' for v in parsed_vals]
                    print(f"  值預覽: {preview_vals}")
                elif error_count == 4:
                    print(f"  (後續錯誤將不再顯示...)")

        if has_identity:
            try:
                cursor.execute(f"SET IDENTITY_INSERT &#91;{table_name}] OFF")
            except:
                pass

        # Accumulate stats per table
        if table_name not in table_stats:
            table_stats&#91;table_name] = {"success": 0, "error": 0}
        table_stats&#91;table_name]&#91;"success"] += success_count
        table_stats&#91;table_name]&#91;"error"] += error_count
        print(f"  本批: 成功 {success_count} 筆, 失敗 {error_count} 筆")

    # Print summary for tables with multiple INSERT batches
    print("\n=== 匯入摘要 ===")
    for tbl, stats in table_stats.items():
        print(f"  {tbl}: 成功 {stats&#91;'success']} 筆, 失敗 {stats&#91;'error']} 筆")

    cursor.close()
    conn.close()
    print("全部完成。")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="MariaDB To MSSQL Migration Tool")
    parser.add_argument("input", help="Path to the .sql dump file")
    args = parser.parse_args()
    
    run_import(args.input)</code></pre>



<p>如果執行過程中遇到記憶體不足的問題，通常是因為 <code>split_values</code> 處理了單一極其巨大的 <code>INSERT</code> 字串。若發生此情況，請告訴我，我們可以改用生成器（Generator）模式來進一步優化字串解析。</p>



<p>上面這個版本針對一般情況是可以使用，針對特定的資料庫欄位類型（例如 Blob 或特殊的日期格式）則需要再進一步的轉換處理。</p>



<p>執行結果:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="528" height="133" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/mstsc_2026-03-16-09-47-1e.jpg?v=1773626286" alt="" class="wp-image-7961"/></figure>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/03/python-mysql-to-mssql-export/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Python MSSQL 資料插入範例</title>
		<link>https://stackoverflow.max-everyday.com/2026/03/python-mssql-insert/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/03/python-mssql-insert/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Mon, 16 Mar 2026 01:43:06 +0000</pubDate>
				<category><![CDATA[Python筆記]]></category>
		<category><![CDATA[mssql]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7957</guid>

					<description><![CDATA[插入成功的執行結果: 要在 Python 中將資...]]></description>
										<content:encoded><![CDATA[
<p>插入成功的執行結果:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="518" height="130" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/03/mstsc_2026-03-16-09-14-1d.jpg?v=1773623811" alt="" class="wp-image-7958"/></figure>



<p>要在 Python 中將資料寫入 MSSQL，最常見且穩定的組合是使用 pyodbc 套件配合微軟官方提供的 ODBC Driver。安裝檔下載:</p>



<p>下載適用於 SQL Server 的 ODBC 驅動程式<br><a href="https://learn.microsoft.com/zh-tw/sql/connect/odbc/download-odbc-driver-for-sql-server?view=sql-server-ver17">https://learn.microsoft.com/zh-tw/sql/connect/odbc/download-odbc-driver-for-sql-server?view=sql-server-ver17</a></p>



<h3 class="wp-block-heading">需安裝的組件</h3>



<p>系統層級需要安裝 Microsoft ODBC Driver for SQL Server。這是微軟提供的驅動程式，讓作業系統能夠與 SQL Server 通訊。建議安裝最新的版本（如 Driver 18 或 17）。</p>



<p>Python 環境則需要安裝 pyodbc 函式庫。你可以透過 pip install pyodbc 指令完成安裝。如果你的專案較具規模，通常也會搭配 sqlalchemy 配合 pandas 來處理大數據量，安裝指令為 pip install sqlalchemy pandas。</p>



<h3 class="wp-block-heading">實作範例</h3>



<p>以下是使用 pyodbc 進行單筆資料插入的標準寫法：</p>



<p>Python</p>



<pre class="wp-block-code"><code>import pyodbc

# 設定連線資訊
conn_config = {
    "DRIVER": "{ODBC Driver 18 for SQL Server}",
    "SERVER": "127.0.0.1", # 如果是本機也可以用 localhost 或 (local)
    "DATABASE": "你的資料庫名稱",
    "UID": "帳號",
    "PWD": "密碼",
    "Encrypt": "yes",
    "TrustServerCertificate": "yes"
}

conn_str = ";".join(&#91;f"{k}={v}" for k, v in conn_config.items()])

def sync_database():
    conn = None
    try:
        # 建立連線
        conn = pyodbc.connect(conn_str)
        cursor = conn.cursor()

        table_name = "UserLogs"
        
        # 1. 檢查資料表是否存在
        check_sql = "SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID(?) AND type = 'U'"
        cursor.execute(check_sql, table_name)
        
        if not cursor.fetchone():
            print(f"資料表 {table_name} 不存在，正在建立...")
            # 2. 建立資料表
            create_sql = f"""
            CREATE TABLE {table_name} (
                ID INT IDENTITY(1,1) PRIMARY KEY,
                UserName NVARCHAR(50),
                ActionTime DATETIME DEFAULT GETDATE(),
                Status NVARCHAR(20)
            )
            """
            cursor.execute(create_sql)
            conn.commit()
            print("資料表建立成功")

        # 3. 執行資料插入
        insert_sql = f"INSERT INTO {table_name} (UserName, Status) VALUES (?, ?)"
        cursor.execute(insert_sql, ("Max", "Active"))
        conn.commit()
        print("資料插入成功")

        # 4. 刪除資料表 (Drop Table)
        print(f"正在刪除資料表 {table_name}...")
        drop_sql = f"DROP TABLE {table_name}"
        cursor.execute(drop_sql)
        conn.commit()
        print("資料表已刪除")

    except pyodbc.Error as e:
        print(f"資料庫操作失敗: {e}")
        if conn:
            conn.rollback()
    finally:
        if conn:
            cursor.close()
            conn.close()

if __name__ == "__main__":
    sync_database()</code></pre>



<h3 class="wp-block-heading">注意事項</h3>



<p>在連線字串中，如果你是連線到本機測試環境且沒有設定 SSL 憑證，務必加上 TrustServerCertificate=yes 參數，否則常會因為加密安全性檢查而導致連線失敗。另外，對於大量資料的寫入，建議使用 cursor.fast_executemany = True 或者是 pandas 的 to_sql 方法，這能顯著提升寫入效能。</p>



<p>在 conn_config 中明確加上了 Encrypt: yes。這是因為 ODBC Driver 18 預設要求加密連線。配合 TrustServerCertificate: yes，可以跳過 SSL 憑證的有效性檢查，通常能解決無法開啟具名管道或連線逾時的問題。</p>



<p>如果你的 SQL Server 是 Express 版本，SERVER 欄位可能需要寫成 127.0.0.1\SQLEXPRESS 這種格式，請根據你的實例名稱進行調整。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/03/python-mssql-insert/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>sqlite 在 multi-threads 情況下同時寫入的問題</title>
		<link>https://stackoverflow.max-everyday.com/2026/03/sqlite-multi-threads-wal/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/03/sqlite-multi-threads-wal/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Wed, 04 Mar 2026 12:42:31 +0000</pubDate>
				<category><![CDATA[Python筆記]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[sqlite]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7816</guid>

					<description><![CDATA[在多執行緒與多核心 CPU 的環境下，使用 Py...]]></description>
										<content:encoded><![CDATA[
<p>在多執行緒與多核心 CPU 的環境下，使用 Python FastAPI 搭配 SQLite 處理多人同時寫入，確實有可能遇到存取錯誤。這主要與 SQLite 的鎖定機制以及 Python 的資料庫驅動程式行為有關。</p>



<h3 class="wp-block-heading">SQLite 的鎖定機制</h3>



<p>SQLite 是一個基於檔案的資料庫，它的併發控制相對單純。當一個進程或執行緒想要寫入資料時，SQLite 會對整個資料庫檔案加上排他鎖（Exclusive Lock）。在預設的資料庫模式下，當某個連線正在寫入，其他連線的讀取或寫入請求都會被阻擋。如果寫入操作耗時過長，其他嘗試寫入的連線會因為等不到鎖而拋出 sqlite3.OperationalError: database is locked 的錯誤。</p>



<h3 class="wp-block-heading">Python 與 FastAPI 的影響</h3>



<p>FastAPI 通常運行在非同步環境下，但標準的 sqlite3 套件是同步的。如果你在 FastAPI 中使用多執行緒（例如透過 thread pool 執行同步函式），多個執行緒同時存取同一個資料庫連線會引發程式崩潰，因為 sqlite3 預設不允許跨執行緒共享連線。即使每個執行緒都有獨立連線，上述的檔案鎖問題依然存在。此外，Python 有全域解釋器鎖（GIL），雖然這在處理 I/O 密集任務時影響較小，但它確保了 Python bytecode 一次只會由一個核心執行，這並不能解決資料庫層級的競爭問題。</p>



<h3 class="wp-block-heading">如何減少存取錯誤</h3>



<p>要讓 SQLite 在多人同時寫入時更穩定，最有效的做法是開啟預寫式日誌（WAL）模式。在 WAL 模式下，讀取和寫入可以同時進行，不會互相阻塞。你可以透過執行 PRAGMA journal_mode=WAL; 來切換。另外，設定適當的 timeout 參數也很重要。在建立連線時設定 sqlite3.connect(db_file, timeout=20)，這會讓連線在遇到鎖定時先等待一段時間，而不是立即報錯。</p>



<h3 class="wp-block-heading">替代方案與考量</h3>



<p>如果你的應用場景真的有非常頻繁的併發寫入需求，SQLite 可能不是最佳選擇。雖然 WAL 模式能改善情況，但 SQLite 終究是為了單機或中輕量級應用設計的。當寫入衝突頻繁到 timeout 都無法解決時，改用像 PostgreSQL 這種客戶端伺服器架構的資料庫會是比較根本的解決辦法，因為它們能處理更細粒度的行級鎖定（Row-level locking），在多核心環境下發揮更好的效能。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p id="p-rc_fe2fd4797b23df9d-16">要在 Python 的 sqlite3 模組中啟用 WAL 模式，你需要在建立資料庫連線後執行一段 PRAGMA 指令。這個設定會儲存在資料庫檔案中，但通常建議在每次程式啟動連線時都確認一次。<sup></sup></p>



<h3 class="wp-block-heading">啟用 WAL 模式的步驟</h3>



<p id="p-rc_fe2fd4797b23df9d-17">在 Python 中，你可以透過執行 execute 方法來切換模式。這會將日誌模式從預設的 DELETE 改為 WAL。<sup></sup></p>



<pre class="wp-block-code"><code>import sqlite3

# 建立連線，建議加上 timeout 避免 busy 錯誤
conn = sqlite3.connect('example.db', timeout=10)

# 啟用 WAL 模式
conn.execute('PRAGMA journal_mode=WAL;')

# 驗證是否成功切換
cursor = conn.execute('PRAGMA journal_mode;')
print(f"目前模式為: {cursor.fetchone()&#91;0]}")

conn.close()
</code></pre>



<h3 class="wp-block-heading">為什麼要在連線時設定</h3>



<p>雖然 WAL 模式一旦設定後會持久化在資料庫標頭中，但在程式碼中明確執行這行指令有助於確保環境一致。當你啟用 WAL 後，你會發現資料庫目錄下多了兩個暫存檔（結尾為 -wal 與 -shm），這是正常現象。</p>



<h3 class="wp-block-heading">在 FastAPI 中的建議配置</h3>



<p>如果你在 FastAPI 中使用，建議在建立連線的工具函式或是 SQLAlchemy 的 engine 配置中加入這個設定。如果你使用 SQLAlchemy，可以使用 event listener 來自動執行。</p>



<pre class="wp-block-code"><code>from sqlalchemy import create_engine, event

engine = create_engine("sqlite:///./test.db")

@event.listens_for(engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
    cursor = dbapi_connection.cursor()
    cursor.execute("PRAGMA journal_mode=WAL")
    cursor.execute("PRAGMA synchronous=NORMAL")
    cursor.close()
</code></pre>



<p id="p-rc_fe2fd4797b23df9d-18">這裡額外加入了 PRAGMA synchronous=NORMAL;，在 WAL 模式下配合這個設定可以大幅提升寫入速度，同時兼顧資料安全性。<sup></sup></p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/03/sqlite-multi-threads-wal/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>ubuntu 24 無法直接安裝 python package</title>
		<link>https://stackoverflow.max-everyday.com/2026/02/ubuntu-24-python-package/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/02/ubuntu-24-python-package/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Mon, 02 Feb 2026 12:59:13 +0000</pubDate>
				<category><![CDATA[Python筆記]]></category>
		<category><![CDATA[電腦相關應用]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7706</guid>

					<description><![CDATA[在 Ubuntu 24.04 中，系統預設安裝 ...]]></description>
										<content:encoded><![CDATA[
<p>在 Ubuntu 24.04 中，系統預設安裝 Python 3.12。為了維護系統穩定，這類較新的 Linux 版本採用了 PEP 668 規範，限制直接使用 pip 將套件安裝到全域環境。如果你直接執行 pip install，通常會看到外部管理環境的錯誤提示。</p>



<h3 class="wp-block-heading">使用虛擬環境安裝</h3>



<p>這是目前最推薦且標準的作法，可以避免不同專案之間的套件衝突。你必須先安裝 venv 工具，然後建立一個獨立的資料夾來存放套件。</p>



<pre class="wp-block-code"><code>sudo apt update
sudo apt install python3-venv
python3 -m venv myenv
source myenv/bin/activate</code></pre>



<p>進入虛擬環境後，終端機提示字元前會出現環境名稱，這時你就可以放心使用 pip install 安裝任何套件，它們會被存放在 myenv 資料夾內。</p>



<h3 class="wp-block-heading">使用 pipx 安裝工具</h3>



<p>如果你想安裝的是像 black、ansible 或 flake8 這種可以在終端機直接執行的工具，而不是要在程式碼裡 import 的函式庫，pipx 是最好的選擇。它會自動幫每個工具建立隔離環境並設定好執行路徑。</p>



<pre class="wp-block-code"><code>sudo apt install pipx
pipx ensurepath
pipx install 套件名稱</code></pre>



<h3 class="wp-block-heading">使用 APT 系統套件管理</h3>



<p>如果你需要的套件非常常見，例如 NumPy 或 Requests，Ubuntu 的官方軟體倉庫通常會有維護好的版本。這些套件會安裝在全域，且由系統統一管理。</p>



<pre class="wp-block-code"><code>sudo apt install python3-numpy</code></pre>



<h3 class="wp-block-heading">強制全域安裝</h3>



<p>雖然非常不建議，但如果你非得在全域環境安裝套件且不在乎系統穩定性，可以使用 break-system-packages 參數來跳過保護機制。請注意這可能會導致 Ubuntu 系統內建的 Python 工具故障。</p>



<pre class="wp-block-code"><code>pip install 套件名稱 --break-system-packages</code></pre>



<p>要退出已經啟動的 Python 虛擬環境，方法非常簡單，只需要在終端機輸入一個指令即可。</p>



<h3 class="wp-block-heading">使用 deactivate 指令</h3>



<p>當你完成工作，想要回到 Ubuntu 系統預設的 Python 環境時，直接輸入：</p>



<pre class="wp-block-code"><code>deactivate</code></pre>



<p>執行後，你會發現終端機提示字元前方的括號環境名稱（例如 (myenv)）消失了，這表示你已經成功登出虛擬環境。這個指令不需要加上 sudo，也不需要路徑，因為在你啟動環境時，deactivate 函式就已經被載入到目前的 shell 階段中。</p>



<h3 class="wp-block-heading">刪除虛擬環境</h3>



<p>如果你不再需要這個虛擬環境，想要徹底移除它，做法並非透過 pip 卸載，而是直接刪除該環境所在的資料夾。</p>



<pre class="wp-block-code"><code>rm -rf myenv</code></pre>



<p>這會刪除所有在該環境中安裝的套件與相關設定，且不會影響到系統其他的 Python 設定。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>python3 -m pip install pr pip-req.txt<br>error: externally-managed-environment</p>



<p>× This environment is externally managed<br>╰─&gt; To install Python packages system-wide, try apt install<br>python3-xyz, where xyz is the package you are trying to<br>install.</p>



<pre class="wp-block-code"><code>If you wish to install a non-Debian-packaged Python package,
create a virtual environment using python3 -m venv path/to/venv.
Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
sure you have python3-full installed.

If you wish to install a non-Debian packaged Python application,
it may be easiest to use pipx install xyz, which will manage a
virtual environment for you. Make sure you have pipx installed.

See /usr/share/doc/python3.12/README.venv for more information.</code></pre>



<p>note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing &#8211;break-system-packages.<br>hint: See PEP 668 for the detailed specification.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>python3 -m venv ./venv<br>The virtual environment was not created successfully because ensurepip is not<br>available. On Debian/Ubuntu systems, you need to install the python3-venv<br>package using the following command.</p>



<pre class="wp-block-code"><code>apt install python3.12-venv</code></pre>



<p>You may need to use sudo with that command. After installing the python3-venv<br>package, recreate your virtual environment.</p>



<p>Failing command: /root/venv/bin/python3</p>



<p>➜ ~ apt install python3-venv</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>在 Ubuntu 24.04 上為 Python 3.12 安裝 MySQL 連接器，最穩定的做法是透過虛擬環境。目前主流有兩種套件選擇：官方的 mysql-connector-python 或社群常用的 mysqlclient。</p>



<h3 class="wp-block-heading">準備系統依賴項目</h3>



<p>在安裝 Python 套件之前，建議先安裝編譯所需的系統開發庫。如果是要安裝 mysqlclient（效能較好），則必須先執行以下指令：</p>



<p>sudo apt update</p>



<p>sudo apt install python3-dev default-libmysqlclient-dev build-essential</p>



<h3 class="wp-block-heading">在虛擬環境中安裝</h3>



<p>首先建立並進入虛擬環境，接著使用 pip 安裝。</p>



<p>python3 -m venv env</p>



<p>source env/bin/activate</p>



<p>如果你想安裝官方提供的連接器：</p>



<p>pip install mysql-connector-python</p>



<p>如果你想安裝效能較佳、符合 Python DB API 規範的套件：</p>



<p>pip install mysqlclient</p>



<h3 class="wp-block-heading">驗證安裝結果</h3>



<p>你可以進入 Python 互動環境測試是否安裝成功：</p>



<p>python</p>



<p>import mysql.connector</p>



<p>print(mysql.connector.<strong>version</strong>)</p>



<p>或是針對 mysqlclient：</p>



<p>python</p>



<p>import MySQLdb</p>



<p>print(MySQLdb.<strong>version</strong>)</p>



<h3 class="wp-block-heading">使用 APT 安裝（全域環境）</h3>



<p>如果你不想使用虛擬環境，而是希望整個系統都能使用，可以使用 Ubuntu 官方維護的套件。這會自動處理所有依賴關係，且不會觸發 PEP 668 的外部環境錯誤。</p>



<p>sudo apt install python3-mysql.connector</p>



<p>這種方式安裝的版本通常比較舊，但保證與系統相容。</p>



<p>需要我提供一段連接 MySQL 資料庫並執行查詢的範例程式碼嗎？</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/02/ubuntu-24-python-package/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>用 Telegram 發送通知</title>
		<link>https://stackoverflow.max-everyday.com/2025/12/telegram-notification-bot/</link>
					<comments>https://stackoverflow.max-everyday.com/2025/12/telegram-notification-bot/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Sun, 28 Dec 2025 21:47:21 +0000</pubDate>
				<category><![CDATA[Python筆記]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7539</guid>

					<description><![CDATA[Telegram 完全免費，沒有訊息則數限制。A...]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="558" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2025/12/telegram-notification-bot-1024x558.jpg?v=1766958403" alt="" class="wp-image-7542" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2025/12/telegram-notification-bot-1024x558.jpg?v=1766958403 1024w, https://stackoverflow.max-everyday.com/wp-content/uploads/2025/12/telegram-notification-bot-600x327.jpg?v=1766958403 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2025/12/telegram-notification-bot-768x419.jpg?v=1766958403 768w, https://stackoverflow.max-everyday.com/wp-content/uploads/2025/12/telegram-notification-bot-1536x838.jpg?v=1766958403 1536w, https://stackoverflow.max-everyday.com/wp-content/uploads/2025/12/telegram-notification-bot.jpg?v=1766958403 1577w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Telegram 完全免費，沒有訊息則數限制。API 穩定又開放。設定過程也不複雜。適合拿來做伺服器監控或程式通知。</p>



<h2 class="wp-block-heading">文章大綱</h2>



<ul class="wp-block-list">
<li>申請機器人 API Token</li>



<li>取得使用者 Chat ID</li>



<li>透過網址發送通知</li>



<li>透過 Python 發送通知</li>



<li>傳送圖片程式碼</li>



<li>傳送圖片附加文字說明</li>



<li>傳送檔案程式碼</li>



<li>機器人群組發訊息</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">申請機器人 API Token</h2>



<p>首先要在 Telegram 上建立一個機器人。打開 Telegram App。在搜尋欄輸入 BotFather。這是官方用來管理機器人的帳號。點進去後按下 Start。</p>



<p>輸入指令 <code>/newbot</code>。系統會請你幫機器人取個顯示名稱。隨便取，自己認得就可以。例如 Max私人秘書1號</p>



<p>接著要設定 username。這個必須是唯一的。而且結尾一定要是 bot。例如 MaxPrivateNotify1_bot。</p>



<p>設定成功後。BotFather 會顯示一串 API Token。這串亂碼就是鑰匙。請妥善保存。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="519" height="598" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2025/12/2025-12-29_05-12_k5.jpg?v=1766956509" alt="" class="wp-image-7540"/></figure>



<h2 class="wp-block-heading">取得使用者 Chat ID</h2>



<p>有了機器人，還需要知道要傳給誰。這個識別碼叫做 Chat ID。先在 Telegram 搜尋你剛剛建立的機器人。點進去按 Start。隨便傳送一個訊息給它，例如 test。這一步是為了讓機器人抓到你的資訊。</p>



<p>接著打開瀏覽器。輸入以下網址。請將網址中的變數換成你剛剛拿到的 Token。</p>



<p><a href="https://api.telegram.org/bot&lt;你的Token&gt;/getUpdates">https://api.telegram.org/bot&lt;你的Token&gt;/getUpdates</a></p>



<p>你會看到網頁顯示一串 JSON 格式的文字。仔細尋找 <code>chat</code> 欄位。裡面的 <code>id</code> 數值就是你的 Chat ID。把它記下來。</p>



<p>以上方法直接照做，會顯示空白資料：</p>



<pre class="wp-block-code"><code>{"ok":true,"result":&#91;]}</code></pre>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="762" height="228" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2025/12/2025-12-29_05-16_k7.jpg?v=1766957097" alt="" class="wp-image-7541" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2025/12/2025-12-29_05-16_k7.jpg?v=1766957097 762w, https://stackoverflow.max-everyday.com/wp-content/uploads/2025/12/2025-12-29_05-16_k7-600x180.jpg?v=1766957097 600w" sizes="auto, (max-width: 762px) 100vw, 762px" /></figure>



<p>這代表機器人目前沒收到新訊息。或是之前的訊息已經過期了。Telegram 的 <code>getUpdates</code> 只能抓到還沒被讀取的最新動態。如果隔太久沒動作，或是沒有發送新訊息，就會回傳空陣列。</p>



<h3 class="wp-block-heading">解決方法</h3>



<p>回到 Telegram App。打開你剛剛建立的機器人視窗。隨便輸入幾個字，例如 123 或 hello。按下發送。</p>



<p>發送成功後，馬上回到瀏覽器。按下重新整理。這時候應該就會看到一長串資料了。</p>



<h3 class="wp-block-heading">尋找 ID 位置</h3>



<p>資料出現後會很雜亂。仔細看 <code>result</code> 裡面。找到 <code>message</code> 這個欄位。接著找 <code>chat</code>。裡面會有一個 <code>id</code> 數值。那個整數就是你要的 chat_id。如果是負數也沒關係，照抄就好。</p>



<h2 class="wp-block-heading">透過網址發送通知</h2>



<p>拿到 Token 和 Chat ID 就能發送訊息。可以直接用瀏覽器測試。輸入以下網址。</p>



<p><a href="https://api.telegram.org/bot&lt;你的Token&gt;/sendMessage?chat_id=&lt;你的ChatID&gt;&amp;text=Hello">https://api.telegram.org/bot&lt;你的Token&gt;/sendMessage?chat_id=&lt;你的ChatID&gt;&amp;text=Hello</a></p>



<p>按下 Enter 後。如果你的 Telegram 跳出通知，顯示 Hello。那就代表設定成功。</p>



<h2 class="wp-block-heading">透過 Python 發送通知</h2>



<p>實際應用上通常是透過程式自動發送。以 Python 為例。使用 requests 套件即可。不需要安裝複雜的 SDK。</p>



<pre class="wp-block-code"><code>import requests

def send_telegram_notify(message):
    # 填入你的 Token 和 Chat ID
    token = "你的API_Token"
    chat_id = "你的Chat_ID"
    
    url = f"https://api.telegram.org/bot{token}/sendMessage"
    payload = {
        "chat_id": chat_id,
        "text": message
    }
    
    try:
        response = requests.get(url, params=payload)
        if response.status_code == 200:
            print("訊息發送成功")
        else:
            print("發送失敗")
    except Exception as e:
        print(f"發生錯誤: {e}")

# 測試呼叫
send_telegram_notify("這是來自 Python 的測試通知")
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>傳送圖片要改打 <code>sendPhoto</code> 這個 API 接口。而且因為涉及檔案上傳，必須使用 POST 方法，不能像傳文字那樣只用 GET。Python 的 requests 套件處理上傳檔案很直覺，只要把檔案物件放進 <code>files</code> 參數裡就好。</p>



<h2 class="wp-block-heading">傳送圖片程式碼</h2>



<p>這段程式碼會讀取電腦裡的圖片檔並傳送出去。</p>



<pre class="wp-block-code"><code>import requests

def send_telegram_photo(image_path):
    # 填入你的 Token 和 Chat ID
    token = "你的API_Token"
    chat_id = "你的Chat_ID"
    
    # 注意網址變成了 sendPhoto
    url = f"https://api.telegram.org/bot{token}/sendPhoto"
    
    try:
        # 用二進位讀取模式打開圖片
        with open(image_path, "rb") as f:
            payload = {"chat_id": chat_id}
            # files 參數對應到 API 的 photo 欄位
            files = {"photo": f}
            
            # 改用 post 方法發送
            response = requests.post(url, data=payload, files=files)
            
            if response.status_code == 200:
                print("圖片發送成功")
            else:
                print("發送失敗")
                
    except FileNotFoundError:
        print("找不到圖片，請檢查路徑")
    except Exception as e:
        print(f"發生錯誤: {e}")

# 測試呼叫，請確保目錄下有這張圖
send_telegram_photo("test.jpg")
</code></pre>



<h2 class="wp-block-heading">注意事項</h2>



<p>圖片檔案太大可能會傳比較久。Telegram 對機器人發送檔案的大小有限制，不過一般幾 MB 的截圖或照片都不會是問題。路徑部分如果不在同一個資料夾，記得要寫絕對路徑。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">傳送圖片附加文字說明</h2>



<p>要在圖片下方附帶文字。不需要分兩次傳送。只要在程式碼的設定裡。多加一個 <code>caption</code> 參數就好。這樣訊息會比較整潔。也不怕圖片跟文字被其他訊息隔開。</p>



<p>這是修改後的版本。函式多了一個 <code>caption_text</code> 的參數。</p>



<pre class="wp-block-code"><code>import requests

def send_photo_with_caption(image_path, caption_text):
    token = "你的API_Token"
    chat_id = "你的Chat_ID"
    
    url = f"https://api.telegram.org/bot{token}/sendPhoto"
    
    try:
        with open(image_path, "rb") as f:
            # 在這裡加入 caption 欄位
            payload = {
                "chat_id": chat_id,
                "caption": caption_text
            }
            files = {"photo": f}
            
            response = requests.post(url, data=payload, files=files)
            
            if response.status_code == 200:
                print("圖片含說明發送成功")
            else:
                print("發送失敗")
                
    except FileNotFoundError:
        print("找不到圖片")
    except Exception as e:
        print(f"發生錯誤: {e}")

# 測試呼叫
send_telegram_photo("test.jpg", "這是今天的監控截圖")
</code></pre>



<h2 class="wp-block-heading">限制提醒</h2>



<p>這個說明文字有長度限制。大約是 1024 個字元。如果要傳送很長的文章。建議還是分開發送。或者把文字寫在第一則。圖片當作第二則補充。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>傳照片雖然方便，但 Telegram 會自動壓縮畫質。如果你要傳送的是 Log 文字檔、Excel 報表，或是想要原始畫質的照片，就要用 <code>sendDocument</code>。這個模式會把檔案當成附件傳送。不會修改檔案內容。</p>



<h2 class="wp-block-heading">傳送檔案程式碼</h2>



<p>邏輯跟傳圖片幾乎一樣。只是把 <code>sendPhoto</code> 改成 <code>sendDocument</code>。然後參數名稱從 <code>photo</code> 改成 <code>document</code>。</p>



<pre class="wp-block-code"><code>import requests

def send_telegram_file(file_path, caption_text=""):
    token = "你的API_Token"
    chat_id = "你的Chat_ID"
    
    # 這裡改成 sendDocument
    url = f"https://api.telegram.org/bot{token}/sendDocument"
    
    try:
        with open(file_path, "rb") as f:
            payload = {
                "chat_id": chat_id,
                "caption": caption_text
            }
            # 這裡的 key 要改成 document
            files = {"document": f}
            
            response = requests.post(url, data=payload, files=files)
            
            if response.status_code == 200:
                print("檔案發送成功")
            else:
                print("發送失敗")
                
    except FileNotFoundError:
        print("找不到檔案")
    except Exception as e:
        print(f"發生錯誤: {e}")

# 測試傳送一個文字檔
# 也可以傳送 zip, pdf, csv 等等
send_telegram_file("server_log.txt", "這是今日的伺服器紀錄")
</code></pre>



<h2 class="wp-block-heading">實用建議</h2>



<p>機器人傳檔限制是 50MB。如果要傳更大的檔案，必須要架設本地伺服器，那會變得很複雜。一般自動化通知，50MB 已經非常夠用了。如果是傳送 .txt 檔，手機版點開可以直接預覽內容，很方便。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">把機器人拉進群組</h2>



<p>流程跟取得個人 ID 很像。先把你的機器人帳號加進去你想通知的群組。就像加入一般朋友那樣。點選群組資訊，選擇加入成員，搜尋你的機器人名字並加入。</p>



<h2 class="wp-block-heading">觸發群組訊息</h2>



<p>機器人剛進群組時，可能因為隱私設定看不到普通對話。為了確保能抓到 ID。建議在群組裡直接 Tag 機器人。或者輸入指令，例如 <code>/hello</code>。只要機器人有被叫到，它就會產生一筆更新資料。</p>



<h2 class="wp-block-heading">取得群組 ID</h2>



<p>動作跟之前一樣。回到瀏覽器重新整理那個 <code>getUpdates</code> 網址。</p>



<p><a href="https://api.telegram.org/bot&lt;你的Token&gt;/getUpdates">https://api.telegram.org/bot&lt;你的Token&gt;/getUpdates</a></p>



<p>這時候找 <code>chat</code> 欄位。你會發現 <code>type</code> 變成了 <code>group</code> 或 <code>supergroup</code>。重點是 <code>id</code> 數值。群組的 ID 通常都是 <strong>負數</strong>。例如 <code>-123456789</code>。這整個包含負號的數字就是群組 ID。</p>



<h2 class="wp-block-heading">程式碼不用改</h2>



<p>拿到這個負數 ID 後。直接把它填進去 Python 程式碼裡的 <code>chat_id</code> 變數。程式碼完全不用動。Telegram API 會自動識別這是要傳給群組。</p>



<h2 class="wp-block-heading">常見問題</h2>



<p>如果你的群組 ID 是 <code>-100</code> 開頭的超級群組。記得那個 <code>-100</code> 也是 ID 的一部分。不要自己把它去掉。複製完整的數字就對了。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>這篇也都是 AI 產生出來的, 比去看 ithelp (iT邦幫忙) 的教學還詳細, 簡潔又易懂…<br>歡迎大家來到「萬事問 AI 」的世界.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2025/12/telegram-notification-bot/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>python logging 高亮實作</title>
		<link>https://stackoverflow.max-everyday.com/2025/12/python-logging-highlight/</link>
					<comments>https://stackoverflow.max-everyday.com/2025/12/python-logging-highlight/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Thu, 25 Dec 2025 02:41:04 +0000</pubDate>
				<category><![CDATA[Python筆記]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7528</guid>

					<description><![CDATA[如果要追求極簡，可以直接捨棄時間戳記，只留下等級...]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="669" height="240" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2025/12/2025-12-25_10-39_k0.jpg" alt="" class="wp-image-7530" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2025/12/2025-12-25_10-39_k0.jpg?v=1766630418 669w, https://stackoverflow.max-everyday.com/wp-content/uploads/2025/12/2025-12-25_10-39_k0-600x215.jpg?v=1766630418 600w" sizes="auto, (max-width: 669px) 100vw, 669px" /></figure>



<p>如果要追求極簡，可以直接捨棄時間戳記，只留下等級名稱與訊息。這樣在開發階段閱讀起來負擔最輕。你可以參考這個格式：</p>



<pre class="wp-block-code"><code>logging.basicConfig(level=logging.INFO, format='%(levelname).1s: %(message)s')
</code></pre>



<p>這個設定會把等級縮寫成一個字，例如 INFO 會變成 I，WARNING 變成 W。輸出的內容會像 <code>I: 這是一條訊息</code>。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">使用 Rich 實作高亮顯示</h3>



<p>內建的 logging 模組沒辦法直接輸出彩色文字。最推薦的方法是安裝 rich 套件。它能自動幫日誌加上顏色，而且格式非常漂亮。</p>



<p>首先在終端機安裝：</p>



<p>pip install rich</p>



<p>接著在程式碼中這樣設定：</p>



<p>Python</p>



<pre class="wp-block-code"><code>import logging
from rich.logging import RichHandler

logging.basicConfig(
    level=logging.INFO,
    format="%(message)s",
    handlers=&#91;RichHandler(show_time=False, show_path=False, markup=True)]
)

log = logging.getLogger("rich")
log.info("這是高亮顯示的訊息")
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">使用 Loguru 替代方案</h3>



<p>如果你不想要複雜的設定，loguru 是另一個很好的選擇。它預設就有漂亮的顏色，且語法非常直覺。</p>



<p>安裝指令：</p>



<p>pip install loguru</p>



<p>使用方式：</p>



<p>Python</p>



<pre class="wp-block-code"><code>from loguru import logger
import sys

# 移除預設設定並自訂簡短格式
logger.remove()
logger.add(sys.stderr, format="&lt;level&gt;{level: &lt;8}&lt;/level&gt; | &lt;level&gt;{message}&lt;/level&gt;", colorize=True)

logger.info("這是一條有顏色的簡短日誌")
</code></pre>



<p>這樣設定後，等級部分會根據嚴重程度顯示不同顏色，訊息本身也會變得容易辨識。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">Uvicorn 的高亮實作</h3>



<p>Uvicorn 本身並沒有使用像 Rich 或 Loguru 這樣的大型第三方高亮套件。它在內部實作了一套簡易的格式化類別。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">核心原理與套件</h3>



<p>Uvicorn 主要透過以下方式實現高亮：</p>



<ul class="wp-block-list">
<li><strong>內建 Formatter</strong>：它自定義了 <code>uvicorn.logging.DefaultFormatter</code> 和 <code>uvicorn.logging.AccessFormatter</code>，這兩個類別會負責處理顏色輸出。</li>



<li><strong>ANSI 轉義碼</strong>：它直接使用 ANSI 顏色碼（如 <code>\x1b[32m</code> 代表綠色）來渲染等級標籤。</li>



<li><strong>Colorama (Windows 專用)</strong>：在 Windows 系統上，為了讓終端機能正確顯示顏色，Uvicorn 會依賴 <strong>colorama</strong> 套件來處理 ANSI 碼的相容性。</li>
</ul>



<h3 class="wp-block-heading">模仿 Uvicorn 的極簡高亮格式</h3>



<p>如果你想要模仿 Uvicorn 那種簡短且帶有顏色的風格，但不想引入重型套件，可以參考它的邏輯來寫一個簡單的 <code>Formatter</code>：</p>



<p>Python</p>



<pre class="wp-block-code"><code>import logging

class SimpleColorFormatter(logging.Formatter):
    # 定義顏色碼
    COLORS = {
        'INFO': "\x1b&#91;32mINFO\x1b&#91;0m",
        'WARNING': "\x1b&#91;33mWARNING\x1b&#91;0m",
        'ERROR': "\x1b&#91;31mERROR\x1b&#91;0m",
        'DEBUG': "\x1b&#91;36mDEBUG\x1b&#91;0m",
    }

    def format(self, record):
        level_name = self.COLORS.get(record.levelname, record.levelname)
        return f"{level_name}: {record.getMessage()}"

# 套用設定
handler = logging.StreamHandler()
handler.setFormatter(SimpleColorFormatter())
logging.getLogger().addHandler(handler)
logging.getLogger().setLevel(logging.INFO)

logging.info("這是仿 Uvicorn 風格的高亮訊息")
</code></pre>



<p>這段程式碼完全不依賴額外套件（除了 Windows 可能需要 <code>pip install colorama</code>），且格式極其精簡。</p>



<p></p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2025/12/python-logging-highlight/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Python 簡體字轉繁體</title>
		<link>https://stackoverflow.max-everyday.com/2025/12/python-opencc/</link>
					<comments>https://stackoverflow.max-everyday.com/2025/12/python-opencc/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Wed, 24 Dec 2025 22:16:03 +0000</pubDate>
				<category><![CDATA[Python筆記]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=7525</guid>

					<description><![CDATA[在 Python 中處理簡繁轉化，最推薦的工具是...]]></description>
										<content:encoded><![CDATA[
<p>在 Python 中處理簡繁轉化，最推薦的工具是 OpenCC。它的準化率很高，也是目前開源社群的主流選擇。</p>



<h3 class="wp-block-heading">安裝 OpenCC</h3>



<p>你需要先安裝 opencc-python-reimplemented 這個庫。它是 OpenCC 的 Python 重新實現版，安裝非常簡單。</p>



<p>Bash</p>



<pre class="wp-block-code"><code>pip install opencc-python-reimplemented
</code></pre>



<h3 class="wp-block-heading">轉換程式碼</h3>



<p>這段程式碼會展示如何將簡體字轉為繁體字。</p>



<p>Python</p>



<pre class="wp-block-code"><code>from opencc import OpenCC

# 初始化轉換器，s2t 代表 Simplified Chinese to Traditional Chinese
cc = OpenCC('s2t')

simple_text = "人工智能改变了世界"
traditional_text = cc.convert(simple_text)

print(traditional_text)
</code></pre>



<h3 class="wp-block-heading">常用轉換模式</h3>



<p>OpenCC 支援多種轉換模式，你可以根據需求更改初始化時的參數。</p>



<ul class="wp-block-list">
<li>s2t：簡體到繁體。</li>



<li>t2s：繁體到簡體。</li>



<li>s2tw：簡體到台灣正體。</li>



<li>s2twp：簡體到台灣正體，並轉換慣用語（例如：軟件變軟體）。</li>
</ul>



<p>這類工具通常只是查表替換，處理單字很快。但如果你需要處理專業術語的對應，建議使用帶有 p 結尾的模式，這樣讀起來會更自然。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2025/12/python-opencc/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
