標籤: 程式設計
按下訂閱鈕透過電子郵件收到我的文章🎉
什麼是套件
當我們運用 Python 程式語言來解決各式各樣的問題(自動化、開發與資料分析…等),最為仰賴的就是套件(Package)功能,一個套件可能包含有資料、函式、類別與文件等,只要從命令列下 pip install 指令安裝、從開發環境下 import 指令載入,就能讓我們「站在巨人的肩膀上」應用定義完善的函式與類別來解決問題。作為一個「自帶電池(Batteries included)」程式語言,套件可以粗分為標準以及第三方兩個生態系,標準套件指的是會伴隨直譯器(Python 軟體基金會版本)而安裝、由軟體基金會維護的套件,諸如 random、datetime、re 等;第三方套件指的是需要額外自行安裝、由第三方團隊或個人維護,諸如 numpy、pandas、matplotlib 等。
什麼是 pip
pip 是 Python 程式語言首屈一指的套件管理系統(Package management system),透過在命令列下各種 pip 指令,可以協助我們從 PyPi(Python Package Index)下載、安裝以及更新電腦中的 Python 套件,亦能夠讓我們檢視套件的資訊或者移除已安裝的套件。
建立套件
建立 Python 套件第一步驟是新增資料夾,並在該資料夾中建立與套件相關的檔案,舉例來說若是希望建立一個套件稱為 covid19-jhu-data,那麼我會新增一個資料夾 packaging_covid19_jhu_data,檔案內容與結構為:
packaging_covid19_jhu_data
├── LICENSE
├── README.md
├── covid19_jhu_data
│ └── __init__.py
├── setup.py
└── tests
2 directories, 4 files
其中 LICENSE 指的是套件授權,開源軟體最常用的授權是 MIT 授權:
Copyright (c) 2020 Kuo, Yao-Jen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
而 README.md 則是所謂的「讀我檔案」,我們很簡單地在裡頭寫一些文字介紹這個套件:
# covid19-jhu-data
This is a simple example package. We use pandas to import data from https://github.com/CSSEGISandData/COVID-19.
資料夾中最重要的是 setup.py,在這個檔案我們會描述套件資訊,由於套件中會使用到 requests 與 pandas,以 install_requires 參數描述依賴套件的名稱與版本:
import setuptools
with open("README.md", "r") as fh:
long_description = fh.read()
setuptools.setup(
name="covid19-jhu-data",
version="0.0.1",
author="Kuo, Yao-Jen",
author_email="yaojenkuo@datainpoint.com",
description="We use pandas to import data from https://github.com/CSSEGISandData/COVID-19",
long_description=long_description,
long_description_content_type="text/markdown",
packages=setuptools.find_packages(),
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
python_requires='>=3.6',
install_requires=[
'requests',
'pandas>=1'
]
)
至於 tests 資料夾是做單元測試之用,目前可以讓它是空的即可。
接著在 __init__.py 中撰寫一個類別 GlobalDailyReport,這個類別有兩個方法:get_latest() 以及 get_historic(year, month, day)。
import datetime
import pandas as pd
class GlobalDailyReport:
def get_latest(self):
"""
This method returns the latest global daily report as a DataFrame.
"""
latest_date = datetime.date.today()
day_delta = datetime.timedelta(days=1)
fmt = '%m-%d-%Y'
while True:
try:
latest_date_fmt = latest_date.strftime(fmt)
csv_url = "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_daily_reports/{}.csv".format(latest_date_fmt)
daily_report = pd.read_csv(csv_url)
print("載入了 {} 的每日報告。".format(latest_date_fmt))
break
except:
latest_date_fmt = latest_date.strftime(fmt)
print("尚未有 {} 的每日報告。".format(latest_date_fmt))
latest_date -= day_delta
return daily_report
def get_historic(self, year, month, day):
"""
This method returns the historic global daily report with specified date as a DataFrame.
"""
csv_file_name = "{}-{}-{}".format(month, day, year)
csv_url = "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_daily_reports/{}.csv".format(csv_file_name)
try:
daily_report = pd.read_csv(csv_url)
print("載入了 {} 的每日報告。".format(csv_file_name))
return daily_report
except:
print("沒有 {} 的每日報告。".format(csv_file_name))
截至於此,套件結構、資訊描述以及主要功能都已經定義完善,接下來要運用 setuptools 以及 wheel 打包成為發布套件(Distribution Package),先安裝(或升級)這兩個套件。
pip install --upgrade setuptools wheel
接著在 packaging_jhu_covid_19_data 資料夾中(也就是與 setup.py 同一層的路徑),執行打包為發布套件的指令。
python3 setup.py sdist bdist_wheel
順利生成發布套件以後,就可以將套件上傳至 PyPi。
上傳套件
前往 PyPi 註冊一個帳號,並在 Account Settings 中新增一個 API Token,成功新增後會得到一組 username 與 password,username 都是 __token__,password 則因人而異。
[pypi]
username = __token__
password = YOUR-PYPI-PASSWORD
將這段 API Token 複製,在電腦的家目錄 /Users/YOURUSERNAME 中新增一個檔案 .pypirc 並貼上。
接著我們將運用 twine 將套件上傳,先安裝(或升級)twine。
pip install --upgrade twine
在 packaging_jhu_covid19_data 資料夾中(也就是與 setup.py 同一層的路徑),執行上傳套件的指令。
python3 -m twine upload dist/*
大功告成!我們即刻就能在 PyPi 上面看到剛才上傳的套件:https://pypi.org/project/covid19-jhu-data,並能用 pip 安裝。
pip install covid19-jhu-data
並可以使用類別 GlobalDailyReport。
from covid19_jhu_data import GlobalDailyReport
gdr = GlobalDailyReport()
latest_daily_report = gdr.get_latest()
first_daily_report = gdr.get_historic('2020', '01', '22')
想暸解哪些主題,留言跟我說👇