<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Python on Quietbo</title><link>https://quietbo.com/tags/python/</link><description>Recent content in Python on Quietbo</description><generator>Hugo -- gohugo.io</generator><language>zh-tw</language><lastBuildDate>Fri, 12 Aug 2022 11:01:01 +0000</lastBuildDate><atom:link href="https://quietbo.com/tags/python/index.xml" rel="self" type="application/rss+xml"/><item><title>[Python] 日誌記錄第三方庫 – Loguru(附簡單的範例)</title><link>https://quietbo.com/2022/08/12/python-%E6%97%A5%E8%AA%8C%E8%A8%98%E9%8C%84%E7%AC%AC%E4%B8%89%E6%96%B9%E5%BA%AB-loguru%E9%99%84%E7%B0%A1%E5%96%AE%E7%9A%84%E7%AF%84%E4%BE%8B/</link><pubDate>Fri, 12 Aug 2022 11:01:01 +0000</pubDate><guid>https://quietbo.com/2022/08/12/python-%E6%97%A5%E8%AA%8C%E8%A8%98%E9%8C%84%E7%AC%AC%E4%B8%89%E6%96%B9%E5%BA%AB-loguru%E9%99%84%E7%B0%A1%E5%96%AE%E7%9A%84%E7%AF%84%E4%BE%8B/</guid><description>&lt;p&gt;use:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;pycharm, FastAPI, Loguru&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;一開始在學log時, 會使用標準庫 logging。&lt;br&gt;
設置上較爲繁瑣, 甚至有些在多進程多線程等特殊處理時, 還會導致日誌記錄會出現異常, 還有幾次都在找為什麼logg會印兩次…&lt;br&gt;
現在單純開發時都會使用Loguru來做一些log的紀錄,下方提供簡單的範例&lt;/p&gt;
&lt;h2 id="安裝"&gt;安裝
&lt;/h2&gt;&lt;p&gt;使用 pip 安裝即可，Python 3 版本的安裝如下：&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;pip3 install loguru&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;log.py&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;from loguru import logger
logger.add("./logs/test.log", rotation="00:00", enqueue=True, retention="30 days")

#logger.info(1)
#logger.error(2)
#logger.warning(3)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;main.py&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;import uvicorn
from log import logger
from fastapi import FastAPI

app = FastAPI()

@app.on_event("startup")
async def startup_event():
 logger.info('Hi startup')

@app.get("/")
async def root():
 return {"message": "Hello World"}


if __name__ == "__main__":
 uvicorn.run("main:app", host='127.0.0.1', port=8000, reload=True)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;執行python main.py&lt;/p&gt;
&lt;p&gt;會看到下方的&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;INFO: Will watch for changes in these directories: ['C:\\Dev\\FastAPI_demo']
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [21476] using watchgod
INFO: Started server process [4168]
INFO: Waiting for application startup.
2022-08-12 18:53:32.579 | INFO | main:startup_event:9 - Hi startup
INFO: Application startup complete.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;打開瀏覽器輸入下方:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;127.0.0.1/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;打開logs資料夾會看到已經有印出來的檔案。&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash line-numbers"&gt;2022-08-12 18:56:21.419 | INFO | main:startup_event:9 - Hi startup
2022-08-12 18:56:27.969 | INFO | main:root:13 - {'message': 'Hello World'}&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>[Python] os.chdir 更改當前工作目錄</title><link>https://quietbo.com/2022/07/19/python-os-chdir-%E6%9B%B4%E6%94%B9%E7%95%B6%E5%89%8D%E5%B7%A5%E4%BD%9C%E7%9B%AE%E9%8C%84/</link><pubDate>Tue, 19 Jul 2022 09:49:44 +0000</pubDate><guid>https://quietbo.com/2022/07/19/python-os-chdir-%E6%9B%B4%E6%94%B9%E7%95%B6%E5%89%8D%E5%B7%A5%E4%BD%9C%E7%9B%AE%E9%8C%84/</guid><description>&lt;p&gt;語法:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="basic" class="language-basic"&gt;os.chdir(path)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;參數&lt;/p&gt;
&lt;ul class="wp-block-list"&gt;
 &lt;li&gt;
 path − 更改到新位置的目錄的完整路徑。
 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;不返回任何值。沒有找到指定的路徑，會拋出FileNotFoundError&lt;/p&gt;
&lt;p&gt;舉例:&lt;br&gt;
我在跟目錄(/)的狀態下, 使用python3 絕對路徑/xxxx.py後, 要在運行別隻py檔案,&lt;/p&gt;
&lt;p&gt;使用下方兩隻py檔來做演示,路徑都在/home/ubuntu/Dev&lt;/p&gt;
&lt;p&gt;檔名:chdir.py&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;#!/usr/bin/python
# -*- coding: UTF-8 -*-

import os, sys

path = "/home/ubuntu/Dev"

# 查看當前工作目錄
retval = os.getcwd()
print("當前工作目錄:%s" % retval)

# 修改當前工作目錄
os.chdir( path )

# 查看修改後的工作目錄
retval = os.getcwd()

print("目錄修改成功:%s" % retval)

# 接著要運行的指令
os.system("python3 pping.py") &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;檔名:pping.py&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;import os
a=os.system("ping 192.168.1.101") #使用a接收返回值
print(a)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;以下是在終端機執行過程:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash line-numbers"&gt;ubuntu@ubuntu:~/Dev$ cd ~
ubuntu@ubuntu:~$ python3 /home/ubuntu/Dev/chdir.py 
當前工作目錄:/home/ubuntu
目錄修改成功:/home/ubuntu/Dev
PING 192.168.1.101 (192.168.1.101) 56(84) bytes of data.
64 bytes from 192.168.1.101: icmp_seq=1 ttl=128 time=5.19 ms&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;由此可見os.getcwd是獲得終端機當下在運行python時的路徑, 而os.chdir是會修改為新的工作路徑, 若沒有修改的話, 是沒辦法透過os.system來運行pping.py的, 會出現找不到檔案的error。&lt;/p&gt;</description></item><item><title>[Python] 背景執行nohup, &amp; 與 nohup.out</title><link>https://quietbo.com/2022/07/06/python-%E8%83%8C%E6%99%AF%E5%9F%B7%E8%A1%8Cnohup-%E8%88%87-nohup-out/</link><pubDate>Wed, 06 Jul 2022 10:13:54 +0000</pubDate><guid>https://quietbo.com/2022/07/06/python-%E8%83%8C%E6%99%AF%E5%9F%B7%E8%A1%8Cnohup-%E8%88%87-nohup-out/</guid><description>&lt;h1 id=""&gt;
&lt;/h1&gt;&lt;p&gt;本篇提到的「&lt;strong&gt;背景&lt;/strong&gt;」指的是: 在終端機模式下使用 [ctrl]-c, 並不會中斷的一個情境!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://quietbo.com/2021/03/10/ubuntu%e8%83%8c%e6%99%af%e5%9f%b7%e8%a1%8cpy%e6%96%b9%e6%b3%95/" target="_blank" rel="noreferrer noopener"&gt;[Linux]背景執行py方法&lt;/a&gt; 雖然是在背景執行, 不會因為[ctrl]-c而中斷, 但會因為「&lt;strong&gt;終端機關閉後而中斷&lt;/strong&gt;」。&lt;/p&gt;
&lt;p id="block-b1f3c7ea-6b97-4897-bb83-e416e7bdabac"&gt;
 中斷可能多個原因, 例如ssh連線到機器後, 操作時不小心將視窗關閉,或是網路斷線而關閉。
&lt;/p&gt;
&lt;p&gt;本次主要目的為: 「&lt;strong&gt;在離線或登出系統後，還能夠讓工作繼續進行&lt;/strong&gt;」。&lt;/p&gt;
&lt;p&gt;演示的code為my_nohup.py:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;# coding:utf-8
from datetime import datetime
from time import sleep
import logging

Log_Format = "%(levelname)s %(asctime)s - %(message)s"

logging.basicConfig(filename = "mylog.log",
 filemode = "w",
 format = Log_Format,
 level = logging.INFO)
logger = logging.getLogger()
logger.error("Our First Log Message")

while(1):
 sleep(5)

 print("print " + str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
 logger.info(str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
 # print(1/0) # 輸出錯誤時使用&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id="指令介紹"&gt;&lt;span class="ez-toc-section" id="%E6%8C%87%E4%BB%A4%E4%BB%8B%E7%B4%B9"&gt;&lt;/span&gt;指令介紹&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h1&gt;&lt;ul class="wp-block-list"&gt;
 &lt;li&gt;
 &lt;code&gt;nohup&lt;/code&gt;: no hang up的縮寫, 不斷地運行。
 &lt;/li&gt;
 &lt;li&gt;
 &lt;code&gt;&amp;&lt;/code&gt;: 在後台運行，關掉終端會停止運行。
 &lt;/li&gt;
 &lt;li&gt;
 &lt;code&gt;&amp;gt;&lt;/code&gt; : 標準輸出符號。
 &lt;/li&gt;
 &lt;li&gt;
 &lt;code&gt;-u&lt;/code&gt;: 在nohup.out內可以看到print的訊息。
 &lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="背景執行nohup-"&gt;&lt;span class="ez-toc-section" id="%E8%83%8C%E6%99%AF%E5%9F%B7%E8%A1%8Cnohup"&gt;&lt;/span&gt;背景執行(nohup, &amp;amp;)&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h2&gt;&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;nohup python3 my_nohup.py &amp;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;758865 為背景執行的PID&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/Ixd9tqD.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;執行完會出現一段，所有輸出都被重定向到一個名為nohup.out的文件中&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;nohup: ignoring input and appending output to 'nohup.out'&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此時輸入ls指令會看到多出mylog.log和nohup.out&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;admins@labs:~$ ls
Dev get-pip.py mylog.log my_nohup.py nohup.out Python-3.7.9&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;試著使用cat去看看這兩隻檔案, mylog.log會每5秒打印訊息, 但nohup.out是空的。&lt;/p&gt;
&lt;p&gt;查看背景運行(若是關閉終端機後才使用指令，jobs已經無法看到後台跑得程序了, 需使用ps aux)&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;jobs -l&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;離開該終端機後, 背景仍會繼續執行這個服務, 可使用ps aux來查看。&lt;/p&gt;
&lt;h2 id="解決-nohupout打開是空白問題"&gt;&lt;span class="ez-toc-section" id="%E8%A7%A3%E6%B1%BA_nohupout%E6%89%93%E9%96%8B%E6%98%AF%E7%A9%BA%E7%99%BD%E5%95%8F%E9%A1%8C"&gt;&lt;/span&gt;[解決] nohup.out打開是空白問題&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h2&gt;&lt;p&gt;如果沒有指定導出的地方, 會在nohup.out檔案內, 但在執行時需使用&lt;br&gt;
python -u&lt;br&gt;
執行時使用下方指令:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;nohup python3 -u my_nohup.py &amp;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;這樣print內的訊息都會在nohup.out了, 而log則是logger寫入的資料, 是分開的檔案。&lt;/p&gt;
&lt;h2 id="指定輸出檔案導出檔案"&gt;&lt;span class="ez-toc-section" id="%E6%8C%87%E5%AE%9A%E8%BC%B8%E5%87%BA%E6%AA%94%E6%A1%88%E5%B0%8E%E5%87%BA%E6%AA%94%E6%A1%88"&gt;&lt;/span&gt;指定輸出檔案(導出檔案)&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h2&gt;&lt;p&gt;可以指定導到其他檔案, 下方是導到my_print.txt&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;nohup python3 -u my_nohup.py &amp;gt; my_print.txt &amp;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;沒有nohup: ignoring input and appending output to ‘nohup.out’的訊息, 也沒有看到nohup.out的檔案。&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/cg3xS8W.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;這裡的&amp;gt;其實是 1&amp;gt; 的縮寫。&lt;figure class="wp-block-table"&gt;&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;名稱&lt;/th&gt;
 &lt;th&gt;代碼&lt;/th&gt;
 &lt;th&gt;操作符號&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;標準輸入&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;td&gt;&amp;lt; 或&amp;laquo;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;標準輸出&lt;/td&gt;
 &lt;td&gt;1&lt;/td&gt;
 &lt;td&gt;&amp;gt;或&amp;raquo;或1&amp;gt; 或1&amp;raquo;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;標準錯誤輸出&lt;/td&gt;
 &lt;td&gt;2&lt;/td&gt;
 &lt;td&gt;2&amp;gt; 或2&amp;raquo;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;通常後台運行重定向可以寫成：&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;mkdir logs
nohup python3 -u my_nohup.py &amp;gt; logs/command.log 2&amp;gt;&amp;1 &amp;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;2&amp;gt;&amp;amp;1 是將「標準錯誤輸出(2)」重定向到「標準輸出(1)」, 簡單來說就是&lt;strong&gt;標準輸出和標準錯誤輸出都在同一份檔案&lt;/strong&gt;, 導入logs文件夾下的command.log日誌文件。&lt;/p&gt;
&lt;h2 id="標準輸出與標準錯誤輸出分開儲存"&gt;&lt;span class="ez-toc-section" id="%E6%A8%99%E6%BA%96%E8%BC%B8%E5%87%BA%E8%88%87%E6%A8%99%E6%BA%96%E9%8C%AF%E8%AA%A4%E8%BC%B8%E5%87%BA%E5%88%86%E9%96%8B%E5%84%B2%E5%AD%98"&gt;&lt;/span&gt;標準輸出與標準錯誤輸出分開儲存&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h2&gt;&lt;p&gt;如果想要把錯誤輸出存到另一份檔案,把最後一行的註解拿掉， print(1/0)在最後運行時會出錯, 下方指令, 會把標準輸出到out.log, 標準錯誤輸出err.log&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;nohup python3 -u my_nohup.py &amp;gt; out.log 2&amp;gt;err.log &amp;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;下方為故意讓程式有出錯的狀況的圖片, 會看到out.log是原本的print日期時間, 而err.log則是遇到錯誤的訊息&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/mMogv4p.png" alt="" /&gt;&lt;/p&gt;
&lt;hr class="wp-block-separator has-alpha-channel-opacity" /&gt;
&lt;p&gt;補充:&lt;br&gt;
&lt;a href="https://linux.vbird.org/linux_basic/centos7/0440processcontrol.php#nohup" target="_blank" rel="noreferrer noopener"&gt;鳥哥私房菜-離線管理問題&lt;/a&gt;&lt;/p&gt;</description></item><item><title>[Python] 日誌按天分割，保存近一個月日誌</title><link>https://quietbo.com/2022/06/30/python-%E6%97%A5%E8%AA%8C%E6%8C%89%E5%A4%A9%E5%88%86%E5%89%B2%EF%BC%8C%E4%BF%9D%E5%AD%98%E8%BF%91%E4%B8%80%E5%80%8B%E6%9C%88%E6%97%A5%E8%AA%8C/</link><pubDate>Thu, 30 Jun 2022 11:00:42 +0000</pubDate><guid>https://quietbo.com/2022/06/30/python-%E6%97%A5%E8%AA%8C%E6%8C%89%E5%A4%A9%E5%88%86%E5%89%B2%EF%BC%8C%E4%BF%9D%E5%AD%98%E8%BF%91%E4%B8%80%E5%80%8B%E6%9C%88%E6%97%A5%E8%AA%8C/</guid><description>&lt;p&gt;下方為code, 請根據自己需求去做調整, 主要是存放的路徑與log內的訊息格式&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;import datetime
import logging
import os
import pathlib
import re
from logging.handlers import TimedRotatingFileHandler


path = os.path.join(pathlib.Path(__file__).parent.absolute(), 'log')
log_folder_path = os.path.join(pathlib.Path(__file__).parent.parent.parent, 'log') # 與service同層, 自行調整parent的次數,

try:
 if not os.path.isdir(log_folder_path): # 如果日誌資料夾不存在，則建立資料夾
 os.mkdir(log_folder_path)
except Exception:
 print("建立資料夾失敗,資料夾路徑：" + log_folder_path)
 pass

log_name = 'serverlog' # 自訂log檔名稱
logger = logging.getLogger(log_name)

log_filename = datetime.datetime.now().strftime("%Y-%m-%d.log")
log_path = os.path.join(log_folder_path, log_name)
logger.setLevel(logging.DEBUG)

# when: 為一天, backupCount: 30個log檔案
file_handler = TimedRotatingFileHandler(
 filename=log_path, when="MIDNIGHT", interval=1, backupCount=30
)
file_handler.suffix = "%Y-%m-%d.log" # 可自訂
file_handler.extMatch = re.compile(r"^\d{4}-\d{2}-\d{2}.log$") # 刪除過期log檔


# format_2 = '[%(asctime)s] [%(process)d] [%(levelname)s] - %(module)s.%(funcName)s (%(filename)s:%(lineno)d) - %(message)s'

# 可自訂想要的格式, 或是網路上提供的, 像format_2就給的訊息很多, 但本身不需要那麼多訊息可以自己訂些簡單的
file_handler.setFormatter(logging.Formatter('[%(asctime)s] %(levelname)1.4s: %(module)s:%(lineno)d %(message)s'))
logger.addHandler(file_handler)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;檔案名稱如下, 名稱會照file_handler.suffix做修正。&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/9v6ifxz.png" alt="" /&gt;&lt;/p&gt;</description></item><item><title>[Python] pymysql.err.IntegrityError 解決</title><link>https://quietbo.com/2022/04/15/python-pymysql-err-integrityerror-%E8%A7%A3%E6%B1%BA/</link><pubDate>Fri, 15 Apr 2022 03:19:05 +0000</pubDate><guid>https://quietbo.com/2022/04/15/python-pymysql-err-integrityerror-%E8%A7%A3%E6%B1%BA/</guid><description>&lt;p&gt;通常遇到這狀況代表有設定unique的欄位, 被重複了,&lt;br&gt;
而且要新增的一筆資料又與該欄位有重複的值,則會報錯,&lt;/p&gt;
&lt;p&gt;假設我的欄位id已經有202204150012的資料時, 要再增加一筆id是202204150012的資料, 錯誤訊息如下, 會告知是哪個欄位重複與重複的value&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;(pymysql.err.IntegrityError) (1062, "Duplicate entry '202204150012' for key 'tb_order.id'")&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解決方式1:&lt;br&gt;
將該欄位的unique拿掉&lt;/p&gt;
&lt;p&gt;解決方式2:&lt;br&gt;
做異常處理與回滾(rollback)&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;try:
 db.commit()
except:
 # 回滾
 db.rollback()
finally:
# 關閉數據庫連接
db.close()&lt;/code&gt;&lt;/pre&gt;
&lt;pre class="wp-block-preformatted"&gt;解決方式3:例外處理時跳過&lt;/pre&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;try:
 .... 
except IntegrityError as error:
 # 獨立處理重複
 result1 = re.search('Duplicate entry', str(error))
 if result1:
 logger.error('Duplicate entry')
 pass
except Exception as error:
 # 其他例外處理 ...
 &lt;/code&gt;&lt;/pre&gt;</description></item><item><title>[Pycharm] 導出&amp;導入虛擬環境(venv導出requirements)</title><link>https://quietbo.com/2022/04/06/pycharm-%E5%B0%8E%E5%87%BA%E5%B0%8E%E5%85%A5%E8%99%9B%E6%93%AC%E7%92%B0%E5%A2%83venv%E5%B0%8E%E5%87%BArequirements/</link><pubDate>Wed, 06 Apr 2022 05:24:22 +0000</pubDate><guid>https://quietbo.com/2022/04/06/pycharm-%E5%B0%8E%E5%87%BA%E5%B0%8E%E5%85%A5%E8%99%9B%E6%93%AC%E7%92%B0%E5%A2%83venv%E5%B0%8E%E5%87%BArequirements/</guid><description>&lt;h2 id="導出虛擬環境"&gt;導出虛擬環境
&lt;/h2&gt;&lt;p&gt;一般命令為導出的是系統環境，不是虛擬環境(venv)&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;pip freeze &amp;gt; requirements.txt&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在windows終端下是不可以使用的，使用以下代碼進行導出，運行後會產生requirements.txt&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;import os
import platform
import sys
import subprocess

# 當前目錄
project_root = os.path.dirname(os.path.realpath(__file__))
# project_root = os.path.realpath(__file__)
print('當前目錄' + project_root)

# 依據目前使用不同的系統會使用不同的command,目前使用linux及Windows
if platform.system() == 'Linux':
 command = sys.executable + ' -m pip freeze &amp;gt; ' + project_root + '/requirements.txt'
if platform.system() == 'Windows':
 command = '"' + sys.executable + '"' + ' -m pip freeze &amp;gt; "' + project_root + '\\requirements.txt"'
# 生成requirements的命令
print(command)
#
# 執行command
# os.system(command) #路徑有空格時不可用
os.popen(command) # 路徑有空格可用&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="安装requirement"&gt;安装requirement
&lt;/h2&gt;&lt;p&gt;開啟新的專案想使用requirement時，打開終端機輸入:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;pip install -r requirement.txt&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>[Python|FastAPI] 返回沒有雙引號的字串(返回純文本)PlainTextResponse</title><link>https://quietbo.com/2022/03/31/pythonfastapi-%E8%BF%94%E5%9B%9E%E6%B2%92%E6%9C%89%E9%9B%99%E5%BC%95%E8%99%9F%E7%9A%84%E5%AD%97%E4%B8%B2%E8%BF%94%E5%9B%9E%E7%B4%94%E6%96%87%E6%9C%ACplaintextresponse/</link><pubDate>Thu, 31 Mar 2022 10:26:15 +0000</pubDate><guid>https://quietbo.com/2022/03/31/pythonfastapi-%E8%BF%94%E5%9B%9E%E6%B2%92%E6%9C%89%E9%9B%99%E5%BC%95%E8%99%9F%E7%9A%84%E5%AD%97%E4%B8%B2%E8%BF%94%E5%9B%9E%E7%B4%94%E6%96%87%E6%9C%ACplaintextresponse/</guid><description>&lt;p&gt;問題:&lt;br&gt;
對方是要的訊息Hello World，不是要”Hello World”&lt;/p&gt;
&lt;p&gt;原本的FastAPI寫法如下:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;from fastapi import FastAPI
import uvicorn

app = FastAPI()


@app.get("/")
async def root():
 return "Hello World"

if __name__ == "__main__":
 uvicorn.run("main:app", host="127.0.0.1", port=8000)&lt;/code&gt;&lt;/pre&gt;&lt;figure class="wp-block-image is-style-default"&gt;
&lt;p&gt;&lt;img decoding="async" src="https://i.imgur.com/f23g0hl.png" alt="" /&gt; &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;可以看到最常見的postman發的請求得到是”Hello World”&lt;/p&gt;
&lt;p&gt;解決方式:&lt;br&gt;
使用:&lt;a class="link" href="https://fastapi.tiangolo.com/advanced/custom-response/#plaintextresponse" target="_blank" rel="noopener"
 &gt;PlainTextResponse&lt;/a&gt;&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;from fastapi import FastAPI
import uvicorn
from fastapi.responses import PlainTextResponse

app = FastAPI()


@app.get("/", response_class=PlainTextResponse)
async def root():
 return "Hello World"

if __name__ == "__main__":
 uvicorn.run("main:app", host="127.0.0.1", port=8000)&lt;/code&gt;&lt;/pre&gt;&lt;figure class="wp-block-image is-style-default"&gt;
&lt;p&gt;&lt;img decoding="async" src="https://i.imgur.com/VHdSY2i.png" alt="" /&gt; &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;可以看到還滿順利的出現了單純只有文字的Hello World&lt;/p&gt;
&lt;p&gt;不一定要放在response_class，以下方式也能成功:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;from fastapi import FastAPI
import uvicorn
from fastapi.responses import PlainTextResponse

app = FastAPI()

def get_text(parameters):
 text = PlainTextResponse(parameters)
 return text


@app.get("/")
async def root():
 op = get_text('hello bocky')
 return op

if __name__ == "__main__":
 uvicorn.run("main:app", host="127.0.0.1", port=8000)&lt;/code&gt;&lt;/pre&gt;&lt;figure class="wp-block-image is-style-default"&gt;
&lt;p&gt;&lt;img decoding="async" src="https://i.imgur.com/VpbKCPd.png" alt="" /&gt; &lt;/figure&gt;&lt;/p&gt;</description></item><item><title>[Python 3.6] f-Strings (字串雙引號前加f)</title><link>https://quietbo.com/2022/02/21/python-3-6-f-strings-%E5%AD%97%E4%B8%B2%E9%9B%99%E5%BC%95%E8%99%9F%E5%89%8D%E5%8A%A0f/</link><pubDate>Mon, 21 Feb 2022 07:03:38 +0000</pubDate><guid>https://quietbo.com/2022/02/21/python-3-6-f-strings-%E5%AD%97%E4%B8%B2%E9%9B%99%E5%BC%95%E8%99%9F%E5%89%8D%E5%8A%A0f/</guid><description>&lt;p&gt;Python 3.6之前式字串格式化:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;str.format()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;處理多個引數和更長的字串時，程式碼很冗長&lt;/p&gt;
&lt;p&gt;f-Strings 比 %-formatting 和 str.format()更輕鬆，且更快。&lt;br&gt;
大小寫f都可以使用:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="basic" class="language-basic"&gt;&amp;gt;&amp;gt;&amp;gt; name = "Bocky"
&amp;gt;&amp;gt;&amp;gt; age = 18
&amp;gt;&amp;gt;&amp;gt; f"name={name}, age={age}"
'name=Bocky, age=18'&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也可以運算:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;&amp;gt;&amp;gt;&amp;gt; f"{2*100}"
'200'&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用function:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;&amp;gt;&amp;gt;&amp;gt; def to_lowercase(input):
... return input.lower()
...
&amp;gt;&amp;gt;&amp;gt; name = "BOCKY"
&amp;gt;&amp;gt;&amp;gt; f"{to_lowercase(name)} is funny."
'bocky is funny.'&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a class="link" href="https://docs.python.org/3/reference/lexical_analysis.html#f-strings" target="_blank" rel="noopener"
 &gt;文檔:2.4.3. Formatted string literals&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://iter01.com/585538.html" target="_blank" rel="noopener"
 &gt;參考2&lt;/a&gt;&lt;/p&gt;</description></item><item><title>[Python] 不打印轉義字符串，字串不轉義處理(\t\f)</title><link>https://quietbo.com/2022/02/17/python-%E4%B8%8D%E6%89%93%E5%8D%B0%E8%BD%89%E7%BE%A9%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%8C%E5%AD%97%E4%B8%B2%E4%B8%8D%E8%BD%89%E7%BE%A9%E8%99%95%E7%90%86tf/</link><pubDate>Thu, 17 Feb 2022 07:26:33 +0000</pubDate><guid>https://quietbo.com/2022/02/17/python-%E4%B8%8D%E6%89%93%E5%8D%B0%E8%BD%89%E7%BE%A9%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%8C%E5%AD%97%E4%B8%B2%E4%B8%8D%E8%BD%89%E7%BE%A9%E8%99%95%E7%90%86tf/</guid><description>&lt;ol class="wp-block-list"&gt;
 &lt;li&gt;
 在轉義字符前多加一個\
 &lt;/li&gt;
 &lt;li&gt;
 字符串前面加上&amp;#8217;r&amp;#8217;
 &lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;print('123\n123\t123')&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;結果如下:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;123
123 123&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在轉義字符前多加一個（\）&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;print('123\\n123\\t123')&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;結果如下:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;123\n123\t123&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用r，整個字串不轉義&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;print(r'123\n123\t123')&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;結果如下:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;123\n123\t123&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="範例.wp-block-heading"&gt;範例
&lt;/h2&gt;&lt;p&gt;最需要注意的是，如果再windows下，如果不使用r，使用\t會出現下圖&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;C:\\Dev\\mytoolbox\\myfile\\testfile.txt&lt;/code&gt;&lt;/pre&gt;
&lt;img decoding="async" src="https://i.imgur.com/SCoKLFT.png" alt="" /&gt; 
會發現\t變成一個tab的功能，但若使用r的話即可解決</description></item><item><title>[Python] Django第一個Urls與View</title><link>https://quietbo.com/2021/11/28/python-django%E7%AC%AC%E4%B8%80%E5%80%8Burls%E8%88%87view/</link><pubDate>Sun, 28 Nov 2021 09:13:19 +0000</pubDate><guid>https://quietbo.com/2021/11/28/python-django%E7%AC%AC%E4%B8%80%E5%80%8Burls%E8%88%87view/</guid><description>&lt;ol class="wp-block-list"&gt;
 &lt;li&gt;
 定義視圖函數&lt;br /&gt;books\views.py:
 &lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;from django.shortcuts import render
from django.http import HttpResponse

#定義視圖函數
def hello(request):
 return HttpResponse("&amp;lt;h1&amp;gt;Hello, world.世界你好.&amp;lt;/h1&amp;gt;")&lt;/code&gt;&lt;/pre&gt;
&lt;ol class="wp-block-list" start="2"&gt;
 &lt;li&gt;
 修改項目(mydjango) urls.py文件
 &lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;from django.contrib import admin
from django.urls import path, include

urlpatterns = [
 path('books/', include('books.urls')),
 path('admin/', admin.site.urls),
]&lt;/code&gt;&lt;/pre&gt;
&lt;ol class="wp-block-list" start="3"&gt;
 &lt;li&gt;
 在books的資料夾新增 urls.py文件
 &lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;from django.urls import path
from . import views

urlpatterns = [
 path('hello/', views.hello, name='hello'),
]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;建立完成後的資料如下，執行&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;python manage.py runserver&lt;/code&gt;&lt;/pre&gt;&lt;figure class="wp-block-image"&gt;
&lt;p&gt;&lt;img decoding="async" src="https://i.imgur.com/A4uX13g.png" alt="" /&gt; &lt;/figure&gt; &lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://i.imgur.com/gkEr4Ol.png" alt="" /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;開啟瀏覽器，輸入&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;http://127.0.0.1:8000/books/hello/&lt;/code&gt;&lt;/pre&gt;&lt;figure class="wp-block-image"&gt;
&lt;p&gt;&lt;img decoding="async" src="https://i.imgur.com/cjoWs3K.png" alt="" /&gt; &lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="url配置"&gt;URL配置
&lt;/h2&gt;&lt;ol class="wp-block-list"&gt;
 &lt;li&gt;
 urlpatterns: 路由模式列表,通過URL模式映射到視圖
 &lt;/li&gt;
 &lt;li&gt;
 path函數： 返回urlpatterns元素&lt;br /&gt;定義：path(route, view, kwargs=None, name=None)&lt;br /&gt;route：路由模式,&lt;br /&gt;view:可以是視圖函數、視圖類或include函數返回值&lt;br /&gt;path(&amp;#8221;, views.home, name=&amp;#8217;home&amp;#8217;)&lt;br /&gt;path(&amp;#8221;, Home.as_view(), name=&amp;#8217;home&amp;#8217;)&lt;br /&gt;path(&amp;#8216;blog/&amp;#8217;, include(&amp;#8216;blog.urls&amp;#8217;))
 &lt;/li&gt;
 &lt;li&gt;
 include函數：導入其他的模塊,include(&amp;#8216;books.urls&amp;#8217;)是導入books.urls模塊
 &lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>[Python] 創建一個Django專案</title><link>https://quietbo.com/2021/11/16/python-%E5%89%B5%E5%BB%BA%E4%B8%80%E5%80%8Bdjango%E5%B0%88%E6%A1%88/</link><pubDate>Mon, 15 Nov 2021 16:08:12 +0000</pubDate><guid>https://quietbo.com/2021/11/16/python-%E5%89%B5%E5%BB%BA%E4%B8%80%E5%80%8Bdjango%E5%B0%88%E6%A1%88/</guid><description>&lt;p&gt;使用：Mac M1&lt;br&gt;
Python 3.8&lt;br&gt;
Django:3.2&lt;/p&gt;
&lt;h2 id="建立環境"&gt;建立環境
&lt;/h2&gt;&lt;p&gt;可參考：&lt;a class="link" href="https://quietbo.com/2021/06/27/mac-pro-m1-%e5%ae%89%e8%a3%9dvirtualenv/" target="_blank" rel="noopener"
 &gt;安裝virtualenv&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;進入env後，安裝及查看Django版本：&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;pip install django
pip list&lt;/code&gt;&lt;/pre&gt;&lt;figure class="wp-block-image"&gt;
&lt;p&gt;&lt;img decoding="async" src="https://i.imgur.com/YDA0rRK.png" alt="" /&gt; &lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="建立專案"&gt;建立專案
&lt;/h2&gt;&lt;p&gt;尋找一個位置，建立第一個專案：&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;django-admin startproject mydjango&lt;/code&gt;&lt;/pre&gt;
&lt;img decoding="async" src="https://i.imgur.com/33w2bsR.png" alt="" /&gt; 
創建的資料結構如下： 
&lt;img decoding="async" src="https://i.imgur.com/AREpKuM.png" alt="" /&gt; 
&lt;p&gt;執行方式：&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;python manage.py runserver&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;若想更改默認端口：&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;python manage.py runserver 0.0.0.0:8899&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;執行成功如下圖：&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/T83LNyC.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;開啟瀏覽器，輸入：&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;http://127.0.0.1:8000/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;第一次運行，會看到下圖畫面：&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/xIuSCBD.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;停止方式：Control + C&lt;/p&gt;
&lt;p&gt;此時，會多出現一個檔案db.sqlite3&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/2pFmXot.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Django主要提供了四種數據庫引擎：&lt;/p&gt;
&lt;ol class="wp-block-list"&gt;
 &lt;li&gt;
 django.db.backends.postgresql
 &lt;/li&gt;
 &lt;li&gt;
 django.db.backends.mysql
 &lt;/li&gt;
 &lt;li&gt;
 django.db.backends.sqlite3
 &lt;/li&gt;
 &lt;li&gt;
 django.db.backends.oracle
 &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;打開setting.py會看到默認引擎是sqlite3，&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases

DATABASES = {
 'default': {
 'ENGINE': 'django.db.backends.sqlite3',
 'NAME': BASE_DIR / 'db.sqlite3',
 }
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class="wp-block-image"&gt;
&lt;p&gt;&lt;img decoding="async" src="https://i.imgur.com/pcR3yH3.png" alt="" /&gt; &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;MySQL設置方式:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;DATABASES = {
 'default': {
 'ENGINE': 'django.db.backends.mysql',
 'NAME': 'djangodb',
 'USER': 'root',
 'PASSWORD': '12345',
 'HOST': '127.0.0.1',
 }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果需要更多的配置信息，可以指定配置文件：&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;DATABASES = {
 'default': {
 'ENGINE': 'django.db.backends.mysql',
 'OPTIONS':{
 'read_default_file': '/path/to/my.cnf',
 },
 }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;配置文件：&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;# my.cnf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;[client]&lt;/p&gt;
&lt;p&gt;databases = djangodb user = root password = 12345 default-character-set=utf8&lt;/p&gt;
&lt;p&gt;PostgreSQL數據庫配置:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;DATABASES = {
 'default': {
 'ENGINE': 'django.db.backends.postgresql',
 'NAME': 'mydatabase',
 'USER': 'mydatabaseuser',
 'PASSWORD': 'mypassword',
 'HOST': '127.0.0.1',
 'PORT': '5432',
 }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;初始化：&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;python manage.py migrate&lt;/code&gt;&lt;/pre&gt;&lt;figure class="wp-block-image"&gt;
&lt;p&gt;&lt;img decoding="async" src="https://i.imgur.com/udBptue.png" alt="" /&gt; &lt;/figure&gt;&lt;/p&gt;
&lt;h3 id="創建應用程序"&gt;創建應用程序
&lt;/h3&gt;&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;python manage.py startapp books&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;生成books，如下的資料結構&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;.
├── books
│&amp;nbsp;&amp;nbsp; ├── __init__.py
│&amp;nbsp;&amp;nbsp; ├── admin.py
│&amp;nbsp;&amp;nbsp; ├── apps.py
│&amp;nbsp;&amp;nbsp; ├── migrations
│&amp;nbsp;&amp;nbsp; │&amp;nbsp;&amp;nbsp; └── __init__.py
│&amp;nbsp;&amp;nbsp; ├── models.py
│&amp;nbsp;&amp;nbsp; ├── tests.py
│&amp;nbsp;&amp;nbsp; └── views.py
├── db.sqlite3
├── manage.py
└── mydjango
 ├── __init__.py
 ├── asgi.py
 ├── settings.py
 ├── urls.py
 └── wsgi.py&lt;/code&gt;&lt;/pre&gt;&lt;figure class="wp-block-image"&gt;
&lt;p&gt;&lt;img decoding="async" src="https://i.imgur.com/RbOLpWV.png" alt="" /&gt; &lt;/figure&gt;&lt;/p&gt;
&lt;ul class="wp-block-list"&gt;
 &lt;li&gt;
 admin :網站管理設置
 &lt;/li&gt;
 &lt;li&gt;
 apps :註冊應用相關
 &lt;/li&gt;
 &lt;li&gt;
 migration ：數據庫的升級文件包，會自動升級專案的數據庫
 &lt;/li&gt;
 &lt;li&gt;
 models ：定義模型
 &lt;/li&gt;
 &lt;li&gt;
 tests :測試相關代碼
 &lt;/li&gt;
 &lt;li&gt;
 views ：定義視圖函式
 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;主要程式撰寫是在views及models&lt;/p&gt;</description></item><item><title>[Python] break、continue、pass、return及exit的用法與區別</title><link>https://quietbo.com/2021/11/05/python-break%E3%80%81continue%E3%80%81pass%E3%80%81return%E5%8F%8Aexit%E7%9A%84%E7%94%A8%E6%B3%95%E8%88%87%E5%8D%80%E5%88%A5/</link><pubDate>Thu, 04 Nov 2021 16:53:04 +0000</pubDate><guid>https://quietbo.com/2021/11/05/python-break%E3%80%81continue%E3%80%81pass%E3%80%81return%E5%8F%8Aexit%E7%9A%84%E7%94%A8%E6%B3%95%E8%88%87%E5%8D%80%E5%88%A5/</guid><description>&lt;ul class="wp-block-list"&gt;
 &lt;li&gt;
 break 結束循環語句
 &lt;/li&gt;
 &lt;li&gt;
 continue 跳出本次循環，繼續下一個循環
 &lt;/li&gt;
 &lt;li&gt;
 pass 不做任何事情，站位而已
 &lt;/li&gt;
 &lt;li&gt;
 return 退出整個函數(def)
 &lt;/li&gt;
 &lt;li&gt;
 exit 結束整個程序(進程)
 &lt;/li&gt;
&lt;/ul&gt;
&lt;div id="ez-toc-container" class="ez-toc-v2_0_82_2 ez-toc-wrap-center counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction"&gt;
 &lt;div class="ez-toc-title-container"&gt;
 &lt;p class="ez-toc-title" style="cursor:inherit"&gt;
 Table of Contents
 &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;span class=&amp;quot;ez-toc-title-toggle&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;#&amp;quot; class=&amp;quot;ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle&amp;quot; aria-label=&amp;quot;顯示/隱藏內容目錄&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;ez-toc-js-icon-con&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;eztoc-hide&amp;quot; style=&amp;quot;display:none;&amp;quot;&amp;gt;Toggle&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;ez-toc-icon-toggle-span&amp;quot;&amp;gt;&amp;lt;svg style=&amp;quot;fill: #999;color:#999&amp;quot; xmlns=&amp;quot;http://www.w3.org/2000/svg&amp;quot; class=&amp;quot;list-377408&amp;quot; width=&amp;quot;20px&amp;quot; height=&amp;quot;20px&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; fill=&amp;quot;none&amp;quot;&amp;gt;&amp;lt;path d=&amp;quot;M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z&amp;quot; fill=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt;&amp;lt;svg style=&amp;quot;fill: #999;color:#999&amp;quot; class=&amp;quot;arrow-unsorted-368013&amp;quot; xmlns=&amp;quot;http://www.w3.org/2000/svg&amp;quot; width=&amp;quot;10px&amp;quot; height=&amp;quot;10px&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; version=&amp;quot;1.2&amp;quot; baseProfile=&amp;quot;tiny&amp;quot;&amp;gt;&amp;lt;path d=&amp;quot;M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z&amp;quot;/&amp;gt;&amp;lt;/svg&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
 &lt;/div&gt;&lt;nav&gt;
 &lt;ul class='ez-toc-list ez-toc-list-level-1 ' &gt;
 &lt;li class='ez-toc-page-1 ez-toc-heading-level-2'&gt;
 &lt;a class="ez-toc-link ez-toc-heading-1" href="https://quietbo.com/2021/11/05/python-break%e3%80%81continue%e3%80%81pass%e3%80%81return%e5%8f%8aexit%e7%9a%84%e7%94%a8%e6%b3%95%e8%88%87%e5%8d%80%e5%88%a5/#break" &gt;break&lt;/a&gt;
 &lt;/li&gt;
 &lt;li class='ez-toc-page-1 ez-toc-heading-level-2'&gt;
 &lt;a class="ez-toc-link ez-toc-heading-2" href="https://quietbo.com/2021/11/05/python-break%e3%80%81continue%e3%80%81pass%e3%80%81return%e5%8f%8aexit%e7%9a%84%e7%94%a8%e6%b3%95%e8%88%87%e5%8d%80%e5%88%a5/#continue" &gt;continue&lt;/a&gt;
 &lt;/li&gt;
 &lt;li class='ez-toc-page-1 ez-toc-heading-level-2'&gt;
 &lt;a class="ez-toc-link ez-toc-heading-3" href="https://quietbo.com/2021/11/05/python-break%e3%80%81continue%e3%80%81pass%e3%80%81return%e5%8f%8aexit%e7%9a%84%e7%94%a8%e6%b3%95%e8%88%87%e5%8d%80%e5%88%a5/#pass" &gt;pass&lt;/a&gt;
 &lt;/li&gt;
 &lt;li class='ez-toc-page-1 ez-toc-heading-level-2'&gt;
 &lt;a class="ez-toc-link ez-toc-heading-4" href="https://quietbo.com/2021/11/05/python-break%e3%80%81continue%e3%80%81pass%e3%80%81return%e5%8f%8aexit%e7%9a%84%e7%94%a8%e6%b3%95%e8%88%87%e5%8d%80%e5%88%a5/#return" &gt;return&lt;/a&gt;
 &lt;/li&gt;
 &lt;li class='ez-toc-page-1 ez-toc-heading-level-2'&gt;
 &lt;a class="ez-toc-link ez-toc-heading-5" href="https://quietbo.com/2021/11/05/python-break%e3%80%81continue%e3%80%81pass%e3%80%81return%e5%8f%8aexit%e7%9a%84%e7%94%a8%e6%b3%95%e8%88%87%e5%8d%80%e5%88%a5/#exit" &gt;exit&lt;/a&gt;
 &lt;/li&gt;
 &lt;/ul&gt;&lt;/nav&gt;
&lt;/div&gt;
&lt;h2 id="break"&gt;&lt;span class="ez-toc-section" id="break"&gt;&lt;/span&gt;break&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h2&gt;&lt;p&gt;用來終止循環語句，即使循環條件沒有False或者序列還沒被完全遞歸完，也會停止執行循環語句。&lt;/p&gt;
&lt;p&gt;break語句用在while和for循環中。&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;def config():
 for num in '12345':
 if num == '3':
 break
 print('當前數字:', num)
 print('=' * 10)

config()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;結果如下：&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;當前數字: 1
當前數字: 2
==========&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="continue"&gt;&lt;span class="ez-toc-section" id="continue"&gt;&lt;/span&gt;continue&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h2&gt;&lt;p&gt;continue 語句跳出&lt;strong&gt;本次&lt;/strong&gt;循環，然後繼續進行下一輪循環。&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;def config():
 for num in '12345':
 if num == '3':
 continue
 print('當前數字:', num)
 print('=' * 10)

config()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;輸出結果：當for迴圈到3時，被跳過了。&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;當前數字: 1
當前數字: 2
當前數字: 4
當前數字: 5
==========&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="pass"&gt;&lt;span class="ez-toc-section" id="pass"&gt;&lt;/span&gt;pass&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h2&gt;&lt;p&gt;空語句，pass 不做任何事情，一般用做佔位語句，是為了保持程序結構的完整性。&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python"&gt;def config():
 for num in '12345':
 if num == '3':
 pass
 print('當前數字:', num)
 print('=' * 10)

config()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;結果如下：&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;當前數字: 1
當前數字: 2
當前數字: 3
當前數字: 4
當前數字: 5
==========&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;補充：&lt;/p&gt;
&lt;blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"&gt;
 &lt;p&gt;
 為什麼要站位？
 &lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;事實上站位就是要先預留位置，回頭再補上具體的代碼實現。
很多時候我們在開發的時候，會把已知的判斷條件或函式寫好，然後在對應的塊中寫上pass，後續再慢慢完善這些站位的部分。&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="return"&gt;&lt;span class="ez-toc-section" id="return"&gt;&lt;/span&gt;return&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h2&gt;&lt;p&gt;return 語句就是將結果返回到調用的地方，並把控制權也一起返回。&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python"&gt;def config():
 for num in '12345':
 if num == '3':
 return f'for迴圈在 {num} 時回傳了'
 print('當前數字:', num)
 print('=' * 10)

print(config())
print('上方function已返回')&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;結果如下：&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;當前數字: 1
當前數字: 2
for迴圈在 3 時回傳了
上方function已返回&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="exit"&gt;&lt;span class="ez-toc-section" id="exit"&gt;&lt;/span&gt;exit&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h2&gt;&lt;p&gt;用來結束整個程序（進程）。&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python"&gt;def config():
 for num in '12345':
 if num == '3':
 exit()
 print('當前數字:', num)
 print('=' * 10)

config()
print('*' * 10) #程式已結束所以不會印出&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;顯示如下：&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;當前數字: 1
當前數字: 2&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>[Python] 有序的Dict – OrderedDict (必學)</title><link>https://quietbo.com/2021/07/22/python-%E6%9C%89%E5%BA%8F%E7%9A%84dict-ordereddict-%E5%BF%85%E5%AD%B8/</link><pubDate>Wed, 21 Jul 2021 17:00:01 +0000</pubDate><guid>https://quietbo.com/2021/07/22/python-%E6%9C%89%E5%BA%8F%E7%9A%84dict-ordereddict-%E5%BF%85%E5%AD%B8/</guid><description>&lt;p&gt;特性:&lt;strong&gt;依據key被插入的先後做排序，如果更新了某個key的值，不會影響排序位置，除非是把key刪除後又重新插入。後續加入的key都會從最末做添加&lt;/strong&gt;。&lt;br&gt;
本篇沒做增刪查改的範例。&lt;/p&gt;
&lt;h2 id="dict一般常用的"&gt;dict(一般常用的)
&lt;/h2&gt;&lt;p&gt;一般常用的dict都會說是無序，但其實還是有一定的順序，是&lt;strong&gt;按照hash來存儲的，和存儲的數據結構有關&lt;/strong&gt;(本篇不多說明)，但通常這個跟我們一般認真的序列有一點不一樣，因為不是填入時的順序。&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;example_dict = dict(
 name='Bocky',
 phone='0912-345-678',
 address='Taiwan-Taipei',
 age='18'
)
print(example_dict)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;輸出結果:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="" class=" line-numbers"&gt;{'phone': '0912-345-678', 'age': '18', 'name': 'Bocky', 'address': 'Taiwan-Taipei'}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="ordereddict"&gt;OrderedDict
&lt;/h2&gt;&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;from collections import OrderedDict
import json
# 錯誤示範，沒有照順序排列的效果(與一般dict結果一樣)
example_ordered_dict_0 = OrderedDict(
 name='Bocky',
 phone='0912-345-678',
 address='Taiwan-Taipei',
 age='18'
)
print('錯誤示範的輸出:\n{}'.format(example_ordered_dict_0))
print("="*20)

example_ordered_dict_1 = OrderedDict([
 ('name', 'Bocky'),
 ('phone_number', '0912-345-678'),
 ('address', 'Taiwan-Taipei'),
 ('age', '18')
])
print("OrderedDict輸出結果:\n{}".format(example_ordered_dict_1))
print("="*20)

print("添加一個key為interest到最末端:")
example_ordered_dict_1['interest'] = 'sleep'
print(example_ordered_dict_1)
print("="*20)

print("把OrderedDict轉成字串,並剔除空白:")
print (json.dumps(example_ordered_dict_1).replace(" ", ""))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;輸出結果:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="" class=" line-numbers"&gt;錯誤示範的輸出:
OrderedDict([('phone', '0912-345-678'), ('age', '18'), ('name', 'Bocky'), ('address', 'Taiwan-Taipei')])
====================
OrderedDict輸出結果:
OrderedDict([('name', 'Bocky'), ('phone_number', '0912-345-678'), ('address', 'Taiwan-Taipei'), ('age', '18')])
====================
添加一個key為interest到最末端:
OrderedDict([('name', 'Bocky'), ('phone_number', '0912-345-678'), ('address', 'Taiwan-Taipei'), ('age', '18'), ('interest', 'sleep')])
====================
把OrderedDict轉成字串,並剔除空白:
{"name":"Bocky","phone_number":"0912-345-678","address":"Taiwan-Taipei","age":"18","interest":"sleep"}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果是要a~z排序的話就使用sorted，網路上很多參考，但這就不需要使用OrderedDict了，一般dict就可以做到，只是排序拼接而已，我自己工作上是很常用:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="" class=" line-numbers"&gt;data = "&amp;".join("{0}={1}".format(str(k), str(example_ordered_dict_1[k])) for k in sorted(example_ordered_dict_1.keys()))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;輸出結果:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="" class=""&gt;address=Taiwan-Taipei&amp;age=18&amp;interest=sleep&amp;name=Bocky&amp;phone_number=0912-345-678&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>[Python]字串轉型態ast.literal_eval，且為什麼不建議eval(必學)</title><link>https://quietbo.com/2021/06/03/python-%E5%AD%97%E4%B8%B2%E8%BD%89%E5%9E%8B%E6%85%8Bast-literal_eval%EF%BC%8C%E4%B8%94%E7%82%BA%E4%BB%80%E9%BA%BC%E4%B8%8D%E5%BB%BA%E8%AD%B0eval%E5%BF%85%E5%AD%B8/</link><pubDate>Thu, 03 Jun 2021 09:40:06 +0000</pubDate><guid>https://quietbo.com/2021/06/03/python-%E5%AD%97%E4%B8%B2%E8%BD%89%E5%9E%8B%E6%85%8Bast-literal_eval%EF%BC%8C%E4%B8%94%E7%82%BA%E4%BB%80%E9%BA%BC%E4%B8%8D%E5%BB%BA%E8%AD%B0eval%E5%BF%85%E5%AD%B8/</guid><description>&lt;p&gt;三分鐘學習一個小知識，還有範例直接看!&lt;/p&gt;
&lt;p&gt;當python在做型態轉換，str轉dict、list、tuple、set或是int時，有些人會使用eval 或 ast.literal_eval，但eval是不推的，安全性是其中重要的原因。&lt;br&gt;
若要單純轉換型態，我。&lt;/p&gt;
&lt;p&gt;稍微講一下eval會說是危險原因:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;# coding:utf-8

"""
輸入下方指令:
"1000"
"1+3"
"[0, 1, [2, 2]]"
"(1, 3, 5, [7])"
"{'A': 'aa', 'B': 'bb', 'C': 'cc'}"
"__import__('os').system('ls /')"
"""
std = input('please input: ')
eval_std = eval(std)
print('input: ',eval_std, type(eval_std))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;以上5種輸入，下方為輸出結果:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;input: 1000 &amp;lt;type 'int'&amp;gt;
input: 4 &amp;lt;type 'int'&amp;gt;
input: [0, 1, [2, 2]] &amp;lt;type 'list'&amp;gt;
input: (1, 3, 5, [7]) &amp;lt;type 'tuple'&amp;gt;
input: {'A': 'aa', 'C': 'cc', 'B': 'bb'} &amp;lt;type 'dict'&amp;gt;

bin boot cdrom dev etc home lib lib32 lib64 libx32 lost+found media mnt opt proc root run sbin snap srv swapfile sys tmp usr var VBox.log
input: 0 &amp;lt;type 'int'&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;eval 不只是可以轉型態、將輸入做處理，甚至系統的命令都能執行!&lt;br&gt;
如果今天(使用者)輸入的內容是輸入刪除文件、顯示目錄結構等命令，那是很大的危險，所以要轉型態是不建議使用eval的!(本篇不介紹惡意操作的指令有哪些)&lt;/p&gt;
&lt;p&gt;使用下方程式:ast.literal_eval&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;# coding:utf-8
import ast

"""
輸入下方指令:
"1000"
"1+3" # 會報錯
"[0, 1, [2, 2]]"
"(1, 3, 5, [7])"
"{'A': 'aa', 'B': 'bb', 'C': 'cc'}"
"__import__('os').system('ls /')" # 會報錯
"""
std = input('please input: ')
ast_std = ast.literal_eval(std)
print('input: %s %s'% (ast_std, type(ast_std)))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ast.literal_eval會去判斷要解析的內容是否安全，不安全就報錯，我們只要處理報錯的處理就好，比起找回刪除的檔案或是被偷的資料，這輕鬆多了。&lt;/p&gt;
&lt;p&gt;結論:字符串進行類型轉換，一律用ast.literal_eval()&lt;/p&gt;
&lt;p&gt;連結:&lt;a class="link" href="https://docs.python.org/2/library/ast.html" target="_blank" rel="noopener"
 &gt;python document&lt;/a&gt;&lt;/p&gt;</description></item><item><title>[Python]實現php serialize函數</title><link>https://quietbo.com/2021/04/28/python%E5%AF%A6%E7%8F%BEphp-serialize%E5%87%BD%E6%95%B8/</link><pubDate>Wed, 28 Apr 2021 08:50:46 +0000</pubDate><guid>https://quietbo.com/2021/04/28/python%E5%AF%A6%E7%8F%BEphp-serialize%E5%87%BD%E6%95%B8/</guid><description>&lt;p&gt;不同的程式語言之間物件的傳遞，就必須把物件序列化為標準格式，比如XML，但更好的方法是序列化為JSON，因為JSON表示出來就是一個字串，可以被所有語言讀取，也可以方便地儲存到磁碟或者通過網路傳輸。&lt;/p&gt;
&lt;p&gt;舉例A公司用php撰寫後序列化(物件轉字串)傳送到B公司，而B公司用Python反序列化時要用到。&lt;br&gt;
通常是用在Python編程環境和PHP編程環境，相互之間需要&lt;code&gt;進行數據交換&lt;/code&gt;時。&lt;figure class="wp-block-image"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img decoding="async" src="https://i.imgur.com/NTe1vwR.png" alt="" /&gt; &lt;/figure&gt;&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;pip3 install phpserialize&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;導入庫：&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;import phpserialize&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;利用dumps 進行序列化（物件轉字串）：&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;phpserialize.dumps(vary)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用loads 進行反序列化（字串轉物件）：&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;phpserialize.loads(formated_string)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a class="link" href="https://blog.csdn.net/whatday/article/details/106987049" target="_blank" rel="noopener"
 &gt;來源1&lt;/a&gt;&lt;/p&gt;</description></item><item><title>[Python]並發編程的三種方式</title><link>https://quietbo.com/2021/04/19/python-%E4%B8%A6%E7%99%BC%E7%B7%A8%E7%A8%8B%E7%9A%84%E4%B8%89%E7%A8%AE%E6%96%B9%E5%BC%8F/</link><pubDate>Mon, 19 Apr 2021 08:07:14 +0000</pubDate><guid>https://quietbo.com/2021/04/19/python-%E4%B8%A6%E7%99%BC%E7%B7%A8%E7%A8%8B%E7%9A%84%E4%B8%89%E7%A8%AE%E6%96%B9%E5%BC%8F/</guid><description>&lt;p&gt;1.多進程(Process)&lt;br&gt;
2.多線程(Thread)&lt;br&gt;
3.多協程(Coroutine)&lt;/p&gt;
&lt;div id="ez-toc-container" class="ez-toc-v2_0_82_2 ez-toc-wrap-center counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction"&gt;
 &lt;div class="ez-toc-title-container"&gt;
 &lt;p class="ez-toc-title" style="cursor:inherit"&gt;
 Table of Contents
 &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;span class=&amp;quot;ez-toc-title-toggle&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;#&amp;quot; class=&amp;quot;ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle&amp;quot; aria-label=&amp;quot;顯示/隱藏內容目錄&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;ez-toc-js-icon-con&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;eztoc-hide&amp;quot; style=&amp;quot;display:none;&amp;quot;&amp;gt;Toggle&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;ez-toc-icon-toggle-span&amp;quot;&amp;gt;&amp;lt;svg style=&amp;quot;fill: #999;color:#999&amp;quot; xmlns=&amp;quot;http://www.w3.org/2000/svg&amp;quot; class=&amp;quot;list-377408&amp;quot; width=&amp;quot;20px&amp;quot; height=&amp;quot;20px&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; fill=&amp;quot;none&amp;quot;&amp;gt;&amp;lt;path d=&amp;quot;M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z&amp;quot; fill=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt;&amp;lt;svg style=&amp;quot;fill: #999;color:#999&amp;quot; class=&amp;quot;arrow-unsorted-368013&amp;quot; xmlns=&amp;quot;http://www.w3.org/2000/svg&amp;quot; width=&amp;quot;10px&amp;quot; height=&amp;quot;10px&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; version=&amp;quot;1.2&amp;quot; baseProfile=&amp;quot;tiny&amp;quot;&amp;gt;&amp;lt;path d=&amp;quot;M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z&amp;quot;/&amp;gt;&amp;lt;/svg&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
 &lt;/div&gt;&lt;nav&gt;
 &lt;ul class='ez-toc-list ez-toc-list-level-1 ' &gt;
 &lt;li class='ez-toc-page-1 ez-toc-heading-level-2'&gt;
 &lt;a class="ez-toc-link ez-toc-heading-1" href="https://quietbo.com/2021/04/19/python-%e4%b8%a6%e7%99%bc%e7%b7%a8%e7%a8%8b%e7%9a%84%e4%b8%89%e7%a8%ae%e6%96%b9%e5%bc%8f/#1%E4%BB%80%E9%BA%BC%E6%98%AFCPU%E5%AF%86%E9%9B%86%E5%9E%8B%E8%A8%88%E7%AE%97%E3%80%81IO%E5%AF%86%E9%9B%86%E5%9E%8B%E8%A8%88%E7%AE%97" &gt;1.什麼是CPU密集型計算、IO密集型計算?&lt;/a&gt;
 &lt;/li&gt;
 &lt;li class='ez-toc-page-1 ez-toc-heading-level-2'&gt;
 &lt;a class="ez-toc-link ez-toc-heading-2" href="https://quietbo.com/2021/04/19/python-%e4%b8%a6%e7%99%bc%e7%b7%a8%e7%a8%8b%e7%9a%84%e4%b8%89%e7%a8%ae%e6%96%b9%e5%bc%8f/#2%E5%A4%9A%E9%80%B2%E7%A8%8B%E3%80%81%E5%A4%9A%E7%B7%9A%E7%A8%8B%E3%80%81%E5%A4%9A%E5%8D%94%E7%A8%8B%E7%9A%84%E5%B0%8D%E6%AF%94" &gt;2.多進程、多線程、多協程的對比&lt;/a&gt;&lt;ul class='ez-toc-list-level-3' &gt;
 &lt;li class='ez-toc-heading-level-3'&gt;
 &lt;a class="ez-toc-link ez-toc-heading-3" href="https://quietbo.com/2021/04/19/python-%e4%b8%a6%e7%99%bc%e7%b7%a8%e7%a8%8b%e7%9a%84%e4%b8%89%e7%a8%ae%e6%96%b9%e5%bc%8f/#%E5%A4%9A%E9%80%B2%E7%A8%8BProcessmultiprocessing" &gt;多進程Process(multiprocessing)&lt;/a&gt;
 &lt;/li&gt;
 &lt;li class='ez-toc-page-1 ez-toc-heading-level-3'&gt;
 &lt;a class="ez-toc-link ez-toc-heading-4" href="https://quietbo.com/2021/04/19/python-%e4%b8%a6%e7%99%bc%e7%b7%a8%e7%a8%8b%e7%9a%84%e4%b8%89%e7%a8%ae%e6%96%b9%e5%bc%8f/#%E5%A4%9A%E7%B7%9A%E7%A8%8BThreadthreading" &gt;多線程Thread(threading)&lt;/a&gt;
 &lt;/li&gt;
 &lt;li class='ez-toc-page-1 ez-toc-heading-level-3'&gt;
 &lt;a class="ez-toc-link ez-toc-heading-5" href="https://quietbo.com/2021/04/19/python-%e4%b8%a6%e7%99%bc%e7%b7%a8%e7%a8%8b%e7%9a%84%e4%b8%89%e7%a8%ae%e6%96%b9%e5%bc%8f/#%E5%A4%9A%E5%8D%94%E7%A8%8BCoroutineasycio_%E2%80%93_%E7%95%B0%E6%AD%A5io" &gt;多協程Coroutine(asycio) &amp;#8211; 異步io&lt;/a&gt;
 &lt;/li&gt;
 &lt;/ul&gt;
 &lt;/li&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;li class='ez-toc-page-1 ez-toc-heading-level-2'&amp;gt;
 &amp;lt;a class=&amp;quot;ez-toc-link ez-toc-heading-6&amp;quot; href=&amp;quot;https://quietbo.com/2021/04/19/python-%e4%b8%a6%e7%99%bc%e7%b7%a8%e7%a8%8b%e7%9a%84%e4%b8%89%e7%a8%ae%e6%96%b9%e5%bc%8f/#3_%E5%A6%82%E4%BD%95%E6%A0%B9%E6%93%9A%E4%BB%BB%E5%8B%99%E9%81%B8%E6%93%87%E5%B0%8D%E6%87%89%E7%9A%84%E6%8A%80%E8%A1%93&amp;quot; &amp;gt;3. 如何根據任務選擇對應的技術?&amp;lt;/a&amp;gt;
&amp;lt;/li&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
 &lt;/ul&gt;&lt;/nav&gt;
&lt;/div&gt;
&lt;h2 id="1什麼是cpu密集型計算io密集型計算"&gt;&lt;span class="ez-toc-section" id="1%E4%BB%80%E9%BA%BC%E6%98%AFCPU%E5%AF%86%E9%9B%86%E5%9E%8B%E8%A8%88%E7%AE%97%E3%80%81IO%E5%AF%86%E9%9B%86%E5%9E%8B%E8%A8%88%E7%AE%97"&gt;&lt;/span&gt;1.什麼是CPU密集型計算、IO密集型計算?&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h2&gt;&lt;p&gt;bound在這邊是限制的意思。&lt;/p&gt;
&lt;p&gt;CPU密集型(CPU-bound):&lt;br&gt;
CPU密集型也叫計算密集型，指的是I/O在很短的時間就可以完成，CPU需要大量的計算和處理。特點是CPU占用率極高。&lt;br&gt;
例如:壓縮/解壓縮、加密/解密、正則表達式搜索。&lt;/p&gt;
&lt;p&gt;IO密集型(I/O-bound):&lt;br&gt;
指的是系統運作大部分的狀況CPU在等I/O的讀寫。CPU占用率相對的會較低。&lt;br&gt;
例如:文件處理、爬蟲網路、讀寫數據庫。&lt;/p&gt;
&lt;p&gt;小總結:&lt;/p&gt;
&lt;blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"&gt;
 &lt;p&gt;
 若程式依賴大量的外部連結(內存、硬碟、網路、DB..等等外部連結)就是IO密集型。若其他的只在CPU運算，則是CPU密集型。
 &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="2多進程多線程多協程的對比"&gt;&lt;span class="ez-toc-section" id="2%E5%A4%9A%E9%80%B2%E7%A8%8B%E3%80%81%E5%A4%9A%E7%B7%9A%E7%A8%8B%E3%80%81%E5%A4%9A%E5%8D%94%E7%A8%8B%E7%9A%84%E5%B0%8D%E6%AF%94"&gt;&lt;/span&gt;2.多進程、多線程、多協程的對比&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h2&gt;&lt;p&gt;這三個是有一個級聯關係的。一個進程中可以包含和啟動多個線程，一個線程中可以啟動多個協程。&lt;br&gt;
協程的概念比較新，在任務中可以啟動很多的協程，但本身都在一個線程中進行。&lt;/p&gt;
&lt;h3 id="多進程processmultiprocessing"&gt;&lt;span class="ez-toc-section" id="%E5%A4%9A%E9%80%B2%E7%A8%8BProcessmultiprocessing"&gt;&lt;/span&gt;多進程Process(multiprocessing)&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h3&gt;&lt;ul class="wp-block-list"&gt;
 &lt;li&gt;
 優點:可以利用多核CPU並行運算
 &lt;/li&gt;
 &lt;li&gt;
 缺點:占用資源最多，可啟動數目比線程少
 &lt;/li&gt;
 &lt;li&gt;
 適用於:CPU密集型計算
 &lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="多線程threadthreading"&gt;&lt;span class="ez-toc-section" id="%E5%A4%9A%E7%B7%9A%E7%A8%8BThreadthreading"&gt;&lt;/span&gt;多線程Thread(threading)&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h3&gt;&lt;ul class="wp-block-list"&gt;
 &lt;li&gt;
 優點:相比進程，更輕量級，占用的資源更少。&lt;br /&gt;這裡的資源指的是每個線程運行都要包含自己的一些變量存儲，存儲到內存區域
 &lt;/li&gt;
 &lt;li&gt;
 缺點:&lt;br /&gt;相比進程:多線程只能併發執行，不能利用多CPU(GIL-全局解釋器鎖)&lt;br /&gt;相比協程:啟動數目有限制，佔用內存資源，有線程切換開銷
 &lt;/li&gt;
 &lt;li&gt;
 適用於:IO密集型計算、同時運型的任務數木要求不多
 &lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="多協程coroutineasycio-8211-異步io"&gt;&lt;span class="ez-toc-section" id="%E5%A4%9A%E5%8D%94%E7%A8%8BCoroutineasycio_%E2%80%93_%E7%95%B0%E6%AD%A5io"&gt;&lt;/span&gt;多協程Coroutine(asycio) – 異步io&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h3&gt;&lt;ul class="wp-block-list"&gt;
 &lt;li&gt;
 優點:內存開銷最少，啟動協程數量最多(甚至到幾萬個)。
 &lt;/li&gt;
 &lt;li&gt;
 缺點:支持的庫有限制(aiohttp vs requests)、代碼實現複雜。&lt;br /&gt;目前有很多技術是不支持協程的，例如requests這個爬蟲常用的類庫，但在python協程中是不支持的，&lt;br /&gt;所以要用協程來進行爬蟲的話，可以用aiohttp。&lt;br /&gt;相比進程、線程，代碼實現複雜，且要考慮的點也較多。
 &lt;/li&gt;
 &lt;li&gt;
 適用於:IO密集型計算、需要超多任務運行、但有現成庫支持的場景。
 &lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="3-如何根據任務選擇對應的技術"&gt;&lt;span class="ez-toc-section" id="3_%E5%A6%82%E4%BD%95%E6%A0%B9%E6%93%9A%E4%BB%BB%E5%8B%99%E9%81%B8%E6%93%87%E5%B0%8D%E6%87%89%E7%9A%84%E6%8A%80%E8%A1%93"&gt;&lt;/span&gt;3. 如何根據任務選擇對應的技術?&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h2&gt;&lt;img decoding="async" src="https://i.imgur.com/yoFF8Xt.png" alt="" /&gt; 
&lt;p&gt;來源:&lt;a class="link" href="https://www.youtube.com/watch?v=qwkc9S85JHs" target="_blank" rel="noopener"
 &gt;youtube&lt;/a&gt;&lt;br&gt;
蚂蚁学Python【Python并发编程】怎样选择多线程多进程多协程&lt;/p&gt;</description></item><item><title>[Linux]背景執行py方法</title><link>https://quietbo.com/2021/03/10/ubuntu%E8%83%8C%E6%99%AF%E5%9F%B7%E8%A1%8Cpy%E6%96%B9%E6%B3%95/</link><pubDate>Wed, 10 Mar 2021 10:33:33 +0000</pubDate><guid>https://quietbo.com/2021/03/10/ubuntu%E8%83%8C%E6%99%AF%E5%9F%B7%E8%A1%8Cpy%E6%96%B9%E6%B3%95/</guid><description>&lt;p&gt;2022/07/06 – 新增&lt;a href="https://quietbo.com/2022/07/06/python-%e8%83%8c%e6%99%af%e5%9f%b7%e8%a1%8cnohup-%e8%88%87-nohup-out/?preview_id=847&amp;preview_nonce=4fb57ac562&amp;preview=true" data-type="URL" data-id="https://quietbo.com/2022/07/06/python-%e8%83%8c%e6%99%af%e5%9f%b7%e8%a1%8cnohup-%e8%88%87-nohup-out/?preview_id=847&amp;preview_nonce=4fb57ac562&amp;preview=true" target="_blank" rel="noreferrer noopener"&gt;[Python] 背景執行nohup, &amp;amp; 與 nohup.out&lt;/a&gt;&lt;/p&gt;
&lt;hr class="wp-block-separator has-alpha-channel-opacity" /&gt;
&lt;p&gt;主要介紹在linux下使用Terminal來背景執行python的幾種方式，&lt;br&gt;
執行3隻python檔，每5秒、10秒、15秒各別顯示當前時間。&lt;/p&gt;
&lt;p&gt;以下為python範例:&lt;br&gt;
test.py、test2.py、test3.py這三隻同時使用背景來執行的畫面。&lt;/p&gt;
&lt;p&gt;執行test.py後，會顯示跳出PID為25270。&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;# coding:utf-8
from datetime import datetime
from time import sleep

while(1):
 count = 1
 sleep(5)
 print(str(count) + " : " + str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果想讓程式跑在背景，在結尾的地方加個&amp;amp;&lt;br&gt;
python 背景執行指令如下:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python"&gt;python 程式碼名稱 &amp;&lt;/code&gt;&lt;/pre&gt;&lt;figure class="wp-block-image"&gt;
&lt;p&gt;&lt;img decoding="async" src="https://i.imgur.com/26SgbQS.png" alt="" /&gt; &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;再執行一隻test2.py，不會讓原本的test.py停住，仍在背景繼續執行，並且顯示test2.py新的PID。&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;# coding:utf-8
from datetime import datetime
from time import sleep

while(1):
 count = 2
 sleep(10)
 print(str(count) + " : " + str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))&lt;/code&gt;&lt;/pre&gt;&lt;figure class="wp-block-image"&gt;
&lt;p&gt;&lt;img decoding="async" src="https://i.imgur.com/qs2nJvo.png" alt="" /&gt; &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;再執行test3.py。&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python line-numbers"&gt;# coding:utf-8
from datetime import datetime
from time import sleep

while(1):
 count = 3
 sleep(15)
 print(str(count) + " : " + str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))&lt;/code&gt;&lt;/pre&gt;&lt;figure class="wp-block-image"&gt;
&lt;p&gt;&lt;img decoding="async" src="https://i.imgur.com/vemyMSe.png" alt="" /&gt; &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;查詢背景運行的程式:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;ps -ef&lt;/code&gt;&lt;/pre&gt;&lt;figure class="wp-block-image"&gt;
&lt;p&gt;&lt;img decoding="async" src="https://i.imgur.com/IczNFtg.png" alt="" /&gt; &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;想停止某隻程式的話，輸入下方指令:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code class=""&gt;kill PID&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;下圖為停止第一支test.py的程式。&lt;/p&gt;
&lt;img decoding="async" src="https://i.imgur.com/XGJJtqK.png" alt="" /&gt; 
kill掉後原本的Terminal會出現已終止的程式名稱。 
&lt;img decoding="async" src="https://i.imgur.com/1If2w51.png" alt="" /&gt; 
原本的test2.py和test3.py還會繼續執行。 
&lt;img decoding="async" src="https://i.imgur.com/ucgmhz8.png" alt="" /&gt;</description></item><item><title>Line bot – 創建Line bot帳號</title><link>https://quietbo.com/2021/03/01/%E5%BE%9E%E9%9B%B6%E9%96%8B%E5%A7%8B%E5%AF%ABline-bot/</link><pubDate>Mon, 01 Mar 2021 15:13:05 +0000</pubDate><guid>https://quietbo.com/2021/03/01/%E5%BE%9E%E9%9B%B6%E9%96%8B%E5%A7%8B%E5%AF%ABline-bot/</guid><description>&lt;div id="ez-toc-container" class="ez-toc-v2_0_82_2 ez-toc-wrap-center counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction"&gt;
 &lt;div class="ez-toc-title-container"&gt;
 &lt;p class="ez-toc-title" style="cursor:inherit"&gt;
 Table of Contents
 &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;span class=&amp;quot;ez-toc-title-toggle&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;#&amp;quot; class=&amp;quot;ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle&amp;quot; aria-label=&amp;quot;顯示/隱藏內容目錄&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;ez-toc-js-icon-con&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;eztoc-hide&amp;quot; style=&amp;quot;display:none;&amp;quot;&amp;gt;Toggle&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;ez-toc-icon-toggle-span&amp;quot;&amp;gt;&amp;lt;svg style=&amp;quot;fill: #999;color:#999&amp;quot; xmlns=&amp;quot;http://www.w3.org/2000/svg&amp;quot; class=&amp;quot;list-377408&amp;quot; width=&amp;quot;20px&amp;quot; height=&amp;quot;20px&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; fill=&amp;quot;none&amp;quot;&amp;gt;&amp;lt;path d=&amp;quot;M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z&amp;quot; fill=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt;&amp;lt;svg style=&amp;quot;fill: #999;color:#999&amp;quot; class=&amp;quot;arrow-unsorted-368013&amp;quot; xmlns=&amp;quot;http://www.w3.org/2000/svg&amp;quot; width=&amp;quot;10px&amp;quot; height=&amp;quot;10px&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; version=&amp;quot;1.2&amp;quot; baseProfile=&amp;quot;tiny&amp;quot;&amp;gt;&amp;lt;path d=&amp;quot;M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z&amp;quot;/&amp;gt;&amp;lt;/svg&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
 &lt;/div&gt;&lt;nav&gt;
 &lt;ul class='ez-toc-list ez-toc-list-level-1 ' &gt;
 &lt;li class='ez-toc-page-1 ez-toc-heading-level-1'&gt;
 &lt;a class="ez-toc-link ez-toc-heading-1" href="https://quietbo.com/2021/03/01/%e5%be%9e%e9%9b%b6%e9%96%8b%e5%a7%8b%e5%af%abline-bot/#%E5%BB%BA%E7%AB%8BHeroku" &gt;建立Heroku&lt;/a&gt;
 &lt;/li&gt;
 &lt;li class='ez-toc-page-1 ez-toc-heading-level-1'&gt;
 &lt;a class="ez-toc-link ez-toc-heading-2" href="https://quietbo.com/2021/03/01/%e5%be%9e%e9%9b%b6%e9%96%8b%e5%a7%8b%e5%af%abline-bot/#%E5%BB%BA%E7%AB%8B_%E5%B1%AC%E6%96%BC%E8%87%AA%E5%B7%B1%E7%9A%84Line_Bot" &gt;建立 屬於自己的Line Bot&lt;/a&gt;
 &lt;/li&gt;
 &lt;li class='ez-toc-page-1 ez-toc-heading-level-1'&gt;
 &lt;a class="ez-toc-link ez-toc-heading-3" href="https://quietbo.com/2021/03/01/%e5%be%9e%e9%9b%b6%e9%96%8b%e5%a7%8b%e5%af%abline-bot/#%E5%B0%87%E5%89%B5%E5%BB%BA%E5%A5%BD%E7%9A%84Line_Bot%E8%88%87Heroku%E9%80%B2%E8%A1%8C%E4%B8%B2%E6%8E%A5" &gt;將創建好的Line Bot與Heroku進行串接&lt;/a&gt;
 &lt;/li&gt;
 &lt;li class='ez-toc-page-1 ez-toc-heading-level-1'&gt;
 &lt;a class="ez-toc-link ez-toc-heading-4" href="https://quietbo.com/2021/03/01/%e5%be%9e%e9%9b%b6%e9%96%8b%e5%a7%8b%e5%af%abline-bot/#%E7%B7%A8%E8%BC%AF%E7%A8%8B%E5%BC%8F" &gt;編輯程式&lt;/a&gt;
 &lt;/li&gt;
 &lt;li class='ez-toc-page-1 ez-toc-heading-level-1'&gt;
 &lt;a class="ez-toc-link ez-toc-heading-5" href="https://quietbo.com/2021/03/01/%e5%be%9e%e9%9b%b6%e9%96%8b%e5%a7%8b%e5%af%abline-bot/#%E5%B0%87%E4%BB%A3%E7%A2%BC%E5%82%B3%E9%80%81%E5%88%B0Heroku%E4%B8%8A" &gt;將代碼傳送到Heroku上&lt;/a&gt;
 &lt;/li&gt;
 &lt;li class='ez-toc-page-1 ez-toc-heading-level-1'&gt;
 &lt;a class="ez-toc-link ez-toc-heading-6" href="https://quietbo.com/2021/03/01/%e5%be%9e%e9%9b%b6%e9%96%8b%e5%a7%8b%e5%af%abline-bot/#Git_%E5%9F%BA%E6%9C%AC%E8%A8%AD%E5%AE%9A%E4%BB%A5%E5%8F%8APush_Hearoku" &gt;Git 基本設定以及Push Hearoku&lt;/a&gt;
 &lt;/li&gt;
 &lt;li class='ez-toc-page-1 ez-toc-heading-level-1'&gt;
 &lt;a class="ez-toc-link ez-toc-heading-7" href="https://quietbo.com/2021/03/01/%e5%be%9e%e9%9b%b6%e9%96%8b%e5%a7%8b%e5%af%abline-bot/#Line_Bot_%E8%88%87_Hearoku_%E7%B6%81%E5%AE%9A" &gt;Line Bot 與 Hearoku 綁定&lt;/a&gt;
 &lt;/li&gt;
 &lt;li class='ez-toc-page-1 ez-toc-heading-level-1'&gt;
 &lt;a class="ez-toc-link ez-toc-heading-8" href="https://quietbo.com/2021/03/01/%e5%be%9e%e9%9b%b6%e9%96%8b%e5%a7%8b%e5%af%abline-bot/#clone_heroku_%E7%9A%84%E7%A8%8B%E5%BC%8F%E7%A2%BC" &gt;clone heroku 的程式碼&lt;/a&gt;
 &lt;/li&gt;
 &lt;/ul&gt;&lt;/nav&gt;
&lt;/div&gt;
&lt;h1 id="建立heroku"&gt;&lt;span class="ez-toc-section" id="%E5%BB%BA%E7%AB%8BHeroku"&gt;&lt;/span&gt;建立Heroku&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h1&gt;&lt;p&gt;首先進到Heroku的帳戶，登入會看到這個畫面&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/VBueQlY.png" alt="" /&gt;&lt;/p&gt;
&lt;p class="has-normal-font-size"&gt;
 &lt;code&gt;Create new app&lt;/code&gt;，創建名字&lt;br /&gt;&lt;img decoding="async" src="https://i.imgur.com/Wrp2hxJ.png" alt="" /&gt;
&lt;/p&gt;
&lt;h1 id="建立-屬於自己的line-bot"&gt;&lt;span class="ez-toc-section" id="%E5%BB%BA%E7%AB%8B_%E5%B1%AC%E6%96%BC%E8%87%AA%E5%B7%B1%E7%9A%84Line_Bot"&gt;&lt;/span&gt;建立 屬於自己的Line Bot&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h1&gt;&lt;p&gt;&lt;a class="link" href="https://developers.line.biz/console/" target="_blank" rel="noopener"
 &gt;&lt;/a&gt;&lt;a href="https://developers.line.biz/console/" data-type="URL" data-id="https://developers.line.biz/console/" target="_blank" rel="noreferrer noopener"&gt;developers網址&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;登入後長下面這樣，點選Create a new provider&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/JuzP1Rg.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;請輸入一個Providers的名稱之後，點擊Create&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/E76NAYa.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;左上角是名字，選擇 Create a Messaging API channel&lt;figure class="wp-block-image"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img decoding="async" src="https://i.imgur.com/soffcDy.png" alt="" /&gt; &lt;/figure&gt; &lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://i.imgur.com/Mt2f6LL.png" alt="" /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;Channel name
Channel description
Category
Subcategory
Email address&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;以上這些填一填，最下方打勾&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/abeUwX2.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;創建完成!&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/DLg4kwQ.png" alt="" /&gt;&lt;/p&gt;
&lt;h1 id="將創建好的line-bot與heroku進行串接"&gt;&lt;span class="ez-toc-section" id="%E5%B0%87%E5%89%B5%E5%BB%BA%E5%A5%BD%E7%9A%84Line_Bot%E8%88%87Heroku%E9%80%B2%E8%A1%8C%E4%B8%B2%E6%8E%A5"&gt;&lt;/span&gt;將創建好的Line Bot與Heroku進行串接&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h1&gt;&lt;p&gt;點選 Messaging API&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/S0Qspyl.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;點選 Auto-reply messages 右邊的 Edit&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/oenU948.png" alt="" /&gt;&lt;br&gt;
點選後會跳出一個新頁面，Webhook設置為啟用&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/5rGURpm.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;點選Channel access token 右方issue，之後會產生一串有英文數字特殊符號的字串，可以先複製起來，後續會使用到。&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/GJkjMqR.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;移動到最上方，選擇Basic settings後，到Channel secret點擊issue，&lt;br&gt;
這串也會跟著改變，也要複製下來，後面會使用到。&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/O6ThIT7.png" alt="" /&gt;&lt;/p&gt;
&lt;h1 id="編輯程式"&gt;&lt;span class="ez-toc-section" id="%E7%B7%A8%E8%BC%AF%E7%A8%8B%E5%BC%8F"&gt;&lt;/span&gt;編輯程式&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h1&gt;&lt;p&gt;填入自己當時複製起來的字串。第一個最長，第二個是比較短的。&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="python" class="language-python"&gt;# Channel Access Token
line_bot_api = LineBotApi('YOUR_CHANNEL_ACCESS_TOKEN')
# Channel Secret
handler = WebhookHandler('YOUR_CHANNEL_SECRET')&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id="將代碼傳送到heroku上"&gt;&lt;span class="ez-toc-section" id="%E5%B0%87%E4%BB%A3%E7%A2%BC%E5%82%B3%E9%80%81%E5%88%B0Heroku%E4%B8%8A"&gt;&lt;/span&gt;將代碼傳送到Heroku上&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h1&gt;&lt;p&gt;到Heroku的官網，依照自己的系統來安裝套件。&lt;a class="link" href="https://devcenter.heroku.com/articles/heroku-cli" target="_blank" rel="noopener"
 &gt;Heroku官網&lt;/a&gt;&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/PpY1C7J.png" alt="" /&gt;&lt;br&gt;
安裝成功後我們來登入Heroku，輸入:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;heroku login&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;會自動開啟新網頁視窗請你登入帳號密碼，下方為登入成功畫面，之後就不需要再管這個畫面了。&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/dXjzRFd.png" alt="" /&gt;&lt;/p&gt;
&lt;h1 id="git-基本設定以及push-hearoku"&gt;&lt;span class="ez-toc-section" id="Git_%E5%9F%BA%E6%9C%AC%E8%A8%AD%E5%AE%9A%E4%BB%A5%E5%8F%8APush_Hearoku"&gt;&lt;/span&gt;Git 基本設定以及Push Hearoku&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h1&gt;&lt;p&gt;查看目前的設定&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;git config --list&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果本來就沒有設定git，需要輸入以下指令來進行初始化:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;git config –global user.name “你的名字”
git config –global user.email “你的信箱”&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在自己的專案創建一個.git檔案(該動作只需要做一次)&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;git init &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;回到資料夾檢查看有沒有出現.git的資料夾，&lt;br&gt;
通常是被隱藏起來，想看的話要把檢視-&amp;gt;隱藏的項目打勾&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/qafdlGn.png" alt="" /&gt;&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/P8iE5aM.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;將 git 資料夾與 Heroku作為連接，這邊HEROKU_APP_NAME是要照你當時在Heroku的專案名稱一樣，&lt;br&gt;
如果不同，他則會報錯&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;heroku git:remote -a {HEROKU_APP_NAME}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;下圖為錯誤訊息:&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/aomEjdG.png" alt="" /&gt;&lt;br&gt;
下圖為設定成功的訊息:&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/mwlCRRR.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;然後照下圖方式&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/axvyAxT.png" alt="" /&gt;&lt;br&gt;
指令如下:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;git add .
git commit -m "你想輸入的訊息(必填)" 
git push -f heroku master&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最後會執行一段時間，成功如下圖&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/ndZrJNC.png" alt="" /&gt;&lt;/p&gt;
&lt;h1 id="line-bot-與-hearoku-綁定"&gt;&lt;span class="ez-toc-section" id="Line_Bot_%E8%88%87_Hearoku_%E7%B6%81%E5%AE%9A"&gt;&lt;/span&gt;Line Bot 與 Hearoku 綁定&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h1&gt;&lt;p&gt;剛剛已經完成將程式碼PUSH到Hearoku了，現在則是讓Line Bot能夠到Hearoku去運行我們想要機器人為我們做的事情。&lt;/p&gt;
&lt;p&gt;回到LINE Developers的Messaging API，&lt;br&gt;
選擇 Webhook URL 點擊Edit 將網址貼上去，格式:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;https://{HEROKU_APP_NAME}.herokuapp.com/callback&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;輸入完後點選Verify，成功後就會將剛剛輸入的URL存上去了。&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/oWzuUvB.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;回到Heroku網站，點選Open app，跳出的新網頁就是你的專案網址。&lt;/p&gt;
&lt;p&gt;測試自己做的機器人回覆內容&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/8Qh5Qm8.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;目前機器人是看打什麼字就回復什麼內容，&lt;br&gt;
如果要關閉每次都跳出那感謝訊息，要到回到回應設定，將自動回覆訊息關閉。&lt;br&gt;
&lt;img decoding="async" src="https://i.imgur.com/JNwMkAj.png" alt="" /&gt;&lt;/p&gt;
&lt;h1 id="clone-heroku-的程式碼"&gt;&lt;span class="ez-toc-section" id="clone_heroku_%E7%9A%84%E7%A8%8B%E5%BC%8F%E7%A2%BC"&gt;&lt;/span&gt;clone heroku 的程式碼&lt;span class="ez-toc-section-end"&gt;&lt;/span&gt;
&lt;/h1&gt;&lt;p&gt;有些人開發不一定是使用同一台電腦，clone的指令如下:&lt;/p&gt;
&lt;pre class="wp-block-code"&gt;&lt;code lang="bash" class="language-bash"&gt;git clone https://git.heroku.com/YOUR_HEROKU_APP_NAME.git&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在&lt;code&gt;YOUR_HEROKU_APP_NAME&lt;/code&gt;這串英文改成你的專案名字就可以成功clone下來了。&lt;/p&gt;</description></item></channel></rss>