almost 4 years ago

  • 前言
    • 這篇心得講些什麼
    • 誰適合看這篇心得
  • 利用Github管理你的專案
    • 開啟一個新專案
    • 觀察repository狀態
    • 將檔案on stage
    • 提交檔案
    • 將repository上傳到遠端
    • 建立可下載的專案包
    • 更新發佈
    • 複習
  • 上傳套件到PyPI
    • 設定setup.py
    • 設定setup.cfg
    • 建立.pypirc設定檔
    • 上傳到PyPI
    • 利用pip下載及安裝
    • 複習
  • 結語
  • 參考資料

前言

說實在的從碩班開始就累積了一些專案,有些是為了研究寫的,有些是個人興趣的小作品,不過就一直放在Lab的server上面覺得有點可惜,前幾天想要把他們整理整理在對外發佈,但這不像是寫blog,打打字放放圖就好了,source code的下載,相關的說明文件,日後版本的更新都是一門學問,只好硬著頭皮好好的搞懂了一下Github和PyPI,本篇算是一個心得隨筆,記錄著這三天以來累積的心得。

這篇心得講些什麼

  1. 簡單的單人git技術(只是用到,不是教學)
  2. 如何使用Github管理你的專案
  3. 發佈一個可供人下載的專案包
  4. Python package的打包
  5. 上傳到PyPI與使用pip下載

誰適合看這篇心得

  1. 對git略懂略懂的人
  2. 專案用Python寫的朋友(不然後半段介紹發佈到PyPI的部份就派不上用場了XD)
  3. 不過還是私心希望越多人看越好。

廢話不多說,馬上來介紹流程。

利用Github管理你的專案

在開始之前,我預設各位都有個想要管理的專案,我給他一個代號:MyProject
以下是他的目錄結構:

MyProject-|--runner
          |--pkgA---|--__init__.py
          |         |--modA_1.py
          |         |--modA_2.py
          |--pkgB---|--__init__.py
                    |--modB.py

然後讀者們已經有了一個Github的帳號了,這邊我們用dokelung這個名稱。

開啟一個新專案

開啟的方法有兩種,一種是使用git init,另一種是直接在Github網站上面點選New repository,我們採用後者:

  1. 輸入repository的名稱: MyProject
  2. 輸入repository的敘述: an example
  3. 勾選initialize this repository with a README
  4. 按下Create repository

Github的repository其實有public和private的差別,但是private需要錢錢,所以我們不用。
但由於public的關係,我們放上去的專案都會變成open source的,這要特別注意。

repository在Github中就是專案的意思。

接著我們來看看MyProject的repository頁面,這個頁面的URL會長這樣:

https://github.com/dokelung/MyProject

我們可以看到在頁面中還有一個HTTPS clone URL,會以repository的名稱來命名:

https://github.com/dokelung/MyProject.git

這是個很重要的位址,只要有他,我們就能隨時透過網路來取得這個專案。

接著我們在本地端,使用git來複製(clone)這個專案:

$ git clone https://github.com/dokelung/MyProject.git

你會發現在當前目錄下多了一個以MyProject為名的目錄,還有一個說明檔README.md
這個目錄不單單是個普通的目錄,還是一個已經使用git來管理的目錄。
不信可以用git status指令來確認:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working directory clean

我們稍微來解釋一下上面的動作:

  1. git status可以幫助我們知道目前專案中各個檔案更動與被追蹤的情形
  2. On branch master告訴我們現在的工作位於master這條分支上,
  3. nothing to commit, working directory clean告訴我們目前這個專案目錄是乾淨的,相較於上ㄧ次的commit是沒有更動的。

觀察repository狀態

接著我們將專案目錄下的所有檔案跟目錄都放到MyProject底下,現在在這個repository目錄底下的結構:

MyProject-|--REDAME.md
          |--runner
          |--pkgA---|--__init__.py
          |         |--modA_1.py
          |         |--modA_2.py
          |--pkgB---|--__init__.py
                    |--modB.py

然後運行git status:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    這邊應該會列出所有你放進來的東西(除了README.md)

nothing added to commit but untracked files present (use "git add" to track)

事實上,每當repository中有檔案更動(包含新增、移入、刪除或修改等),git status總是會指出更動的部份。
目前的更動是,git發現了一群沒看過的檔案。

將檔案on stage

若我們想要讓這些檔案被真正的納入repository中(現在只是在該目錄下,實際上還沒加入repository),我們必須使用git add指令:

$ git add runner
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   runner

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    除了README.md和runner之外的所有東西

git add會將指定的檔案狀態成為stage,講簡單一點就是ready to commit的意思!
反之,unstage的檔案將不會被commit:有兩種狀況會產生unstage檔案:

  1. 未被追蹤的檔案
  2. 被追蹤但是被修改過而且尚未被add的檔案

關於第二點,我們可以藉由修改一個原本onstage的檔案再用git add來觀察。
總之,利用git status可看的清清楚楚所有的狀態。
我們只要記住,所有需要被提交的檔案都要確定是stage狀態的。

大家可以將專案裡面的檔案都git add進去囉。

有個情況比較特別,當某個on stage的檔案被刪除後,若要加入這項刪除的資訊,請用git rm

提交檔案

使用git commit做提交。

$ git commit -m "first commit"

"first commit"是該次提交的註解。
所謂提交,就好像是一次存檔,我們可以任意的更動專案,並使用git add讓檔案on stage,調整出一個要存檔的狀態(stage狀態的檔案們就是要被存檔的檔案),然後用git commit來進行真正的存檔。

本篇不是git教學,就不贅述了XD

將repository上傳到遠端

光在本地端存檔還不夠,我們既然要用Github管理我們的專案,自然要將檔案提交到遠端囉,使用git push就好:

$ git push

由於我們的repository是從Github建的,所以預設的遠端就是Github囉。另外,如果日後在遠端有任何修改,先用git pull將遠端merge回來,在git push推出去。

到這邊,我們已經能夠在遠端好好管理我們的專案了,很棒吧。

建立可下載的專案包

首先,我們要對重要的commit(重要的存檔,也就是你想要發佈的那次存檔)製作一個標籤,使用git tag即可:

$ git tag v1.0 -m "first realease"

通常tag的名稱會是一個版本號,要不要使用v來標示版本都可以,-m後面跟著的一樣是該標籤之註解。
接著,我們將標籤推到遠端:

$ git push --tags origin master

如此一來,我們將可以獲得可供下載的專案包:

https://github.com/dokelung/MyProject/tarball/v1.0

或是在Github的頁面上也有相應的zip檔或tar.gz檔下載URL。

更新發佈

新手可能會有一個問題,當我們需要更新某個已發佈的專案包而不是建立一個新版本時,該怎麼做呢?
通常會想到的辦法是移除舊有的版本發佈,再重新建立一個,這讓過程很麻煩,因為你需要:

  1. 刪除本地端tag
  2. 刪除遠端tag
  3. 建立本地端tag
  4. 建立遠端tag

上述動作是針對同一個版本的標籤,因為不同版本的標籤我們直接新建立就好,沒有刪除的問題。

但是只要用-f選項就可以強制更新囉(下面假設v1.0標籤已經存在):

git tag v1.0 -f -m "update release"
git push -f --tags origin master

複習

我們重點整理複習一下:

  1. 整備本地專案
  2. 上Github開新repository
  3. 利用HTTPS clone URL和git clone將repository拉到本地
  4. 將本地專案放入git repository在本地的目錄
  5. 使用git add將所有檔案加入追蹤
  6. 使用git commit將stage上的檔案進行提交
  7. 使用git push將repository提交到遠端

若該次commit想要發佈,則:

  1. 使用git tag建立版本標籤
  2. 使用git push --tags提交標籤至遠端

若專案有檔案被修改,重複步驟5-7。
若同一版本的專案要重新發佈,使用-f選項。

上傳套件到PyPI

緊接著是第二個部分,若我們的專案是python package或是python script,如何利用PyPI將之散播到全世界。

設定setup.py

相信大家都知道,如果自己的python專案想要讓大家能夠安裝到python環境中,一定要撰寫setup.py,這邊針對還要上傳到PyPI,來客製化我們的setup.py,我們先來檢視一下目前的結構和等等我們要加入的幾個設定檔位置:

MyProject-|--REDAME.md
          |--setup.py  <-- 加入setup.py
          |--setup.cfg <-- 加入setup.cfg
          |--.pypirc   <-- 加入.pypirc(注意,此檔不要加入stage提交出去!)
          |--runner
          |--pkgA---|--__init__.py
          |         |--modA_1.py
          |         |--modA_2.py
          |--pkgB---|--__init__.py
                    |--modB.py

然後:

setup.py
from distutils.core import setup

setup(
    name = 'MyProject',
    packages = ['pkgA', 'pkgB'],
    scripts = ['runner'],
    version = '1.0',
    description = 'My first project',
    author = 'dokelung',
    author_email = 'dokelung@gmail.com',
    url = 'https://github.com/dokelung/MyProject',
    download_url = 'https://github.com/dokelung/MyProject/tarball/v1.0',
    keywords = ['Good Project'],
    classifiers = [],
)

以下針對各欄位進行說明:

欄位名稱 描述
name 專案名稱
packages 要安裝的套件名稱
scripts script名稱,通常代表一個執行檔,不一定有
version 版本
description 專案描述
author 作者
author_email 作者信箱
url 專案頁面,這邊我們填上Github的專案位址
download_url 下載路徑,還記得我們剛剛傳上標籤後得到的URL嗎?就是他
keywords 這個專案的一些關鍵字

這邊稍微解釋一下scripts,這邊要寫在scripts裡的可能是整個專案的執行檔,用到了專案裡面的套件,為了要將該檔案同時也裝到使用者的系統上,我們需要把他也標註上去,否則後面我們利用pip安裝的時候就只會安裝package而不會安裝執行檔了。
而這邊所謂的安裝,其實也就是把指定的scripts放到一個可執行路徑裡,例如/usr/bin/中,如此使用者在安裝完後可在任何地方運行該script。

有兩點要說明一下,第一個是我們能夠指定安裝的路徑,但如果只給script名稱,那他會被放在預設的位置。
第二點是,一定要注意script的名字不要跟他要匯入的pakcage同名了,這會導致一些import上的失誤。

至此,已經擁有一個漂亮的安裝檔了(同時也能支援PyPI發佈)。

設定setup.cfg

因為我們的README.md是個markdown file,所以我們得新增一個setup.cfg的檔案:

[metadata]
description-file = README.md

建立.pypirc設定檔

唯有建立此設定檔才能讓我們傳東西到PyPI上面:

.pypirc
[distutils]
index-servers =
    pypi 

[pypi] 
repository: https://pypi.python.org/pypi
username: dokelung
password: 寫自己的吧,我才不會告訴你我的咧!

再次提醒大家,既然裡面有密碼明碼,大家千萬不要把它給commit出去。

上傳到PyPI

終於到了最後一個階段,首先註冊:

$ python setup.py register -r pypi

接著上傳:

$ python setup.py sdist upload -r pypi

太好了,你成功的讓全世界都能看到你的作品了,上PyPI看看你的package頁面吧。

利用pip下載及安裝

這應該是過程中最讓人開心的部分了,我們可以嘗到甜美的果實,利用

$ pip install MyProject

我們可以在任何有裝pip的電腦中下載及安裝我們的專案,很酷吧!
而如果日後我們的專案有任何修改,除了上一大節提到的重新提交或發佈外,如果要在PyPI上面進行更新,一定要重新上傳過喔。

複習

又到了複習的時間囉,我們來看看後半段怎麼做的:

  1. 撰寫setup.py
  2. 撰寫setup.cfg如果README是markdown file
  3. 撰寫.pypirc
  4. python setup.py register註冊
  5. python setup.py sdist upload上傳

若有任何更動,請先整理Github再修改setup.py的內容(如更新版本號或是加入新套件或更正URL)重複4-5。

結語

原本想要寫個簡明的流程,沒想到比我想的篇幅還要大,我想我應該有點完美主義者的傾向XDD
再者,由於這篇心得不是git的教學,所以有許多部分沒有細講,建議大家去瀏覽一下相關的教學,有個滿推薦的blog大家可以在參考資料的地方看到。

參考資料

推薦的git教學

← Python教學投影片 Django筆記 - Python的模組與套件 →
 
comments powered by Disqus