2013年10月20日 星期日

[Pyhotn] 使用 PyInstaller 打包 python 程式

PyInstaller 可以用來把 Python 程式打包起來,方便在其他機器上執行,

省去安裝 Python 以及所使用套件的時間(尤其在 windows 上)

安裝 PyInstaller

先到 官網 下載 PyInstaller 的壓縮檔,並且解壓縮,放置到適合的路徑即可。

使用方式

使用方式的部份大致分為兩部份介紹。

第一個比較簡單的使用方式是直接使用 PyInstaller 內的 pyinstaller.py

例如現在寫好了一個 hello.py 接著使用 pyinstaller.py

$ python path_to_PyInstaller/pyinstaller.py [OPTION] xxx.py

ex.

$ python path_to_PyInstaller/pyinstaller.py --onefile hello.py

執行後 pyinstaller 會為你的程式產生一個 .spec 檔(類似 makefile 的東西)

並且依據內容產生執行檔(pyinstaller 會提示你執行檔的位置)。

OPTION 的部份可以 $ python pyinstaller.py --help 查看,底下也列出一些供參考

--onefile           製作出獨立的執行檔
--onedir            製作出的檔案街放在同一個目錄下(預設值)
--tk                製作包含TCL/TK的檔案。
--windowed          製作視窗程式。(程式執行時不會有文字視窗出現)
--console           製作一般的console程式。
--upx               製作透過UPX壓縮過的執行檔。
--icon=<FILE.ICO>   指定程式的圖示。
--version=<FILE>    指定程式的版本資訊(需要準備一個檔案放這些資訊)。
--name=<NAME>       指定程式的名稱。若無此選項,則主script檔案的名稱將被使用。

另外有時可能 pyinstaller 沒有辦法正確分析程式相依性,或者有特別需求時可能需要

先修改 .spec 檔在打包,又或者要使用現有的 .spec 檔打包時可以參考下列作法。

首先先使用 utils/Makespec.py 產生 .spec 檔

$ python path_to_PyInstaller/utils/Makespec.py [OPTION] xxx.py

ex.

$ python path_to_PyInstaller/utils/Makespec.py [OPTION] hello.py

接著便會產生與主程式同名的 hello.spec 便可以對他先做需要的修改, .spec 的內容大致如下

# -*- mode: python -*-
a = Analysis(['hello.py'],
             pathex=['/tmp'],
             hiddenimports=[],
             hookspath=None)
pyz = PYZ(a.pure)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          name=os.path.join('dist', 'hello'),
          debug=False,
          strip=None,
          upx=True,
          console=True )

以筆者為例曾經在打包一個以 WxPython 撰寫的程式,打包完後執行會有以下的錯誤

ImportError: No module named scipy.sparse.csgraph._validation

那網路上查到比較多的作法都是在主程式裡加上一些 import 好讓

pyinstaller 可以正確的分析出這個相依性這個相依性,不過這個作法讓我不太舒服,

因為一些檢查語法的 plugin 一樣找不到這個相依性,就會提醒我 import 了一個沒用到的東西,

所以我決定把他寫進 .spec 中,在 .spec 裡有個 Analysis 的項目其中有個 hiddenimports,

以筆者的例子就需要把 scipy.sparse.csgraph._validation 這個 module 加進去,像是這樣

# -*- mode: python -*-
a = Analysis(['hello.py'],
             pathex=['/tmp'],
             hiddenimports=['scipy.sparse.csgraph._validation'],
             hookspath=None)

..... 後略

這樣 pyinstaller 就會把這個 module 一同打包起來,就可以解決這個問題了。

編寫好 .spec 後就可以使用 utils/Build.py 來打包

$ python path_to_PyInstaller/utils/Build.py xxx.spec

ex.

$ python path_to_PyInstaller/utils/Build.py hello.spec

執行結果基本上和第一部份的相同。

2013年9月21日 星期六

製作 gif 動畫

製作 gif 動畫

因為看到了一些 vim plugin 利用 gif 動畫來 Demo plugin 的效果,

最近也自己在寫 vim plugin 所以也想來做看看,

製作過程分成三個步驟

錄製影片

首先我利用 kazam 來錄製影片,選用 kazam 的原因是因為他可以利用拖拉的方式來選取

錄製範圍,雖然在一些小地方的中文顯示有點問題,不過不影響使用。

將影片轉成 gif 檔

接下來使用 mplayer 把影片轉換成 gif 檔。

mplayer input.mp4 -ao null -vo gif89a:fps=13 output=output.gif

另外可以加上 -ss-endpos 來設定轉換的時間起點和長度,

這部份可以參考後面附的參考資料。

壓縮 gif 檔

由於轉換出來的 gif 檔案會很大,以我自己錄製的檔案為例,

原本解析度 818x502 時間長度 37 秒總共大小才 662 KB 的 mp4 影片,

轉換成 gif 檔後竟然有 8.2 MB,這樣放在網頁上的載入時間怕會有點久,

所以利用 convert 幫他瘦身一下

convert output.gif -fuzz 10% -layers Optimize optimised.gif

剛剛提到的檔案瘦身之後剩下 666 KB。

我錄起來的結果是有些小地方不太清楚,不知道像 YouCompleteMe 的是怎麼錄的,

感覺就蠻清晰的 Orz,我自己錄的在這 easyreST

2013年7月2日 星期二

[rsST] 修改 rst2html highlight style

[reST] 修改 rst2html code highlight sytle

不知道為什麼上一篇裝完新的 rst2html 轉出來的 syntax highlight 超醜,明明 restview 弄出來得很漂亮阿....

rst2html 不加參數

https://github.com/float-tw/float-blog/raw/master/img/rst2html.jpeg

restview

https://github.com/float-tw/float-blog/raw/master/img/restview.jpeg

查了一下可以從 pygmentize 匯出 syntax highlight 的 css (來源):

$ pygmentize -S default -f html -a .highlight > style.css

匯出以後會得到一個像這樣的檔案:

.highlight .hll { background-color: #ffffcc }
.highlight  { background: #f8f8f8; }
.highlight .c { color: #408080; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #008000; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #BC7A00 } /* Comment.Preproc */

接下來看一下把這段 code 原本用 rst2html 轉換後的結果

int main()
{
    int x;
    printf("hello\n");
    return 0;
}
$ rst2html test.rst > test.html
<pre class="code c literal-block">
<span class="keyword type">int</span> <span class="name function">main</span><span class="punctuation">()</span>
<span class="punctuation">{</span>
    <span class="keyword type">int</span> <span class="name">x</span><span class="punctuation">;</span>
    <span class="name">printf</span><span class="punctuation">(</span><span class="literal string">&quot;hello</span><span class="literal string escape">\n</span><span class="literal string">&quot;</span><span class="punctuation">);</span>
    <span class="keyword">return</span> <span class="literal number integer">0</span><span class="punctuation">;</span>
<span class="punctuation">}</span>
</pre>

接下來需要修改一下 rst2html 的參數和剛剛的 sytle.css 讓 css 可以正確生效

首先是 <pre> 的 class 部份 code-block 轉換出來的是 code 而 sytle.css 裡面用的是 highlight 所以要先把 highlight 都改成 code:

.code .hll { background-color: #ffffcc }
.code  { background: #f8f8f8; }
.code .c { color: #408080; font-style: italic } /* Comment */
.code .err { border: 1px solid #FF0000 } /* Error */
.code .k { color: #008000; font-weight: bold } /* Keyword */
.code .o { color: #666666 } /* Operator */
.code .cm { color: #408080; font-style: italic } /* Comment.Multiline */
.code .cp { color: #BC7A00 } /* Comment.Preproc */

接著是不同部份所使用 highlight 的 class 原本轉出來的結果是使用較長的敘述,

這部份需要在 rst2html 加上 --syntax-highlight=short

使他使用簡短敘述,完成後同時指定 --stylesheet=style.css 使用剛剛的 css:

$ rst2html.py --stylesheet=style.css --syntax-highlight=short test.rst > test.html

轉換完的 html

<pre class="code c literal-block">
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">x</span><span class="p">;</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">&quot;hello</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>

使用後的結果就如這裡所示

2013年6月29日 星期六

[reST] Code Syntax Highlight

[reST] Code Syntax Highlight

今天參加了 Tainan.py X MOSUT 的聚會,其中一個主題是 sphinx 的文件教學,

sphinx 的文件是用 reStructuredText 撰寫的,講者 demo 的時候剛好 demo 到了在 reST 裡面使用 code syntax highlight

當初要開始用 reST 寫部落格的時候也稍微作過一些功課,只是 syntax highlight 的部份沒有試出來,

今天聽完分享後在繼續查了些資料,我原本用來轉換的 rst2html 是 Docutils 所帶的,當使用 code-block 區塊的時候,像是:

.. code-block:: c

    int main()
    {
        printf("hello\n");
        return 0;
    }

是會發生錯誤的:

$ rst2html test.rst > test.html
test.rst:1: (ERROR/3) Unknown directive type "code-block".

.. code-block:: c

    int main()
    {
        printf("hello\n");
        return 0;
    }

接著找到這篇發現 Docutils 0.9 的版本後就支援了 code-block 而 Ubuntu 12.04.2 所套件庫裡的 Docutils 卻是 0.8.1:

$ rst2html --version
rst2html (Docutils 0.8.1 [release], Python 2.7.3, on linux2)

所以我就把他移除了(怒),接著從 pip 安裝 Docutils:

$ sudo apt-get remove docutils
$ sudo pip install docutils

目前 pip 上的 Docutils 是 0.10 版,趕快來試用一下

int main()
{
    printf("hello\n");
    return 0;
}

哈,太好了可以用了 :)

2013年6月12日 星期三

[Convert] 將文字轉成圖片

[Convert] 將文字轉成圖片

有時候在簡報或者寫 blog 時會有需要將一些輸出結果呈現出來的時候,

螢幕截圖是一個不錯的方式,不過截圖可能會比較模糊而且麻煩,

最近發現 convert 就有附帶一個功能是將文字直接轉換成圖片,用在這個地方剛剛好。

首先先舉個用 convert 將文字轉成圖片的例子:

$ convert -size 64x32 label:float convert_label.jpeg

指定大小 64x32 文字內容為 float 就可以得到以下圖片

https://github.com/float-tw/float-blog/raw/master/img/convert_label.jpeg

接下來要把 ifconfig lo 的結果轉換成圖片,首先先看一下原本的執行結果:

$ ifconfig lo
lo    Link encap:Local Loopback
      inet addr:127.0.0.1  Mask:255.0.0.0
      inet6 addr: ::1/128 Scope:Host
      UP LOOPBACK RUNNING  MTU:16436  Metric:1
      RX packets:38990 errors:0 dropped:0 overruns:0 frame:0
      TX packets:38990 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:0
      RX bytes:4280371 (4.2 MB)  TX bytes:4280371 (4.2 MB)

那我們可以用 pipe 導給 convert 將結果轉成圖片:

$ ifconfig lo | convert label:@- convert_label_ifconfig.jpeg

label:@- 的部份是表示 label 的內容由標準輸入取得,就可以得到

https://github.com/float-tw/float-blog/raw/master/img/convert_label_ifconfig.jpeg

當然我們也可以指定圖片為黑底白字:

$ ifconfig lo | convert -background black -fill white label:@- convert_label_ifconfig_black.jpeg
https://github.com/float-tw/float-blog/raw/master/img/convert_label_ifconfig_black.jpeg

當然 label 在使用上還有很多參數可以使用,這部份可以參考這片 [1] 以及官方的範例 [2]

2013年6月8日 星期六

[Linux] 使用 convert 做圖片轉檔

[Linux] 使用 convert 做圖片轉檔

convert 是 ImageMagick 的一個 CLI tool

所以安裝 ImageMagick 就可以得到他了!

可以用來做圖片轉檔,調整大小,也還有其他很強大的功能

這邊簡單介紹一下圖片轉檔和調整大小的方法

首先,圖片轉檔的部份非常簡單舉個例子,如果要把 png 檔轉成 jpeg 檔:

convert input.png outpu.jpeg

好了,就這樣,要轉的檔名放前面,輸出檔名放後面,convert 會自己根據副檔名做轉換

簡單吧。

調整大小的話:

convert input.png -resize 64x64 output.png

這樣就可以把圖片縮放到可以放入 64x64 的方形內,

那如果要把他轉成真的是 64x64 呢?加上驚嘆號強制調整,像這樣:

convert input.png -resize 64x64\! output.png

倒斜線是有時候因為 shell 的關係可能驚嘆號是脫逸字元,有時不加也是可以的。

2013年6月2日 星期日

[Linux] 文字檔編碼工具

[Linux] 文字檔編碼工具

一開使用這些工具是因為在 linux 下的 smplayer 在載入影片字幕的時候,

雖然設定成解 big5 編碼,可是還是會有部份的字變成亂碼,

把字幕檔轉成 UTF-8 就沒有這個問題了,另外偶爾也會遇到 code 裡面有中文註解,

用 gedit 開會有解碼錯誤的問題,或是一些原本 windows 底下的檔案。

iconv

沒記錯的話 ubuntu 12.04 預設是有安裝,

最早用的工具,因為參數蠻好記的範例如下:

iconv -f big5 -t utf8 -o output.txt input.txt

-f form-code

-t to-code

-o 輸出檔名

enca

用了一段時間後突然想到,是不是應該在轉換前先檢查一下檔案原本的編碼是什麼,

因為偶爾也會遇到簡體的編碼,

一開始想到的是用 file ,的確 file 可以用來檢查編碼,

不過後來發現了一個缺點,big5 編碼的檔案會被誤認成 ISO-8859,

所以就查到了這個,Ubuntu 12.04 預設沒有安裝 apt-get install enca 一下就可以了。:

enca input.txt

就可以檢查檔案編碼了,在 manpage 裡面可以查到他支援的編碼,測了幾個檔案 big5 可以正常偵測

另外更強大的是這個 enconv 他可以用來直接把檔案轉成系統的編碼:

enconv input.txt

假設系統編碼是 utf-8 而 input.txt 是 big5 編碼,那 input.txt 就會被轉成 utf-8,

非常的方便,完全不需要什麼參數 :)

當然,這兩個工具都有其他更多的參數可以使用,有興趣的可以問一下男人,

另外還有看到其他的工具像是 convmv 參數跟 iconv 類似,不過就沒有裝來玩了。

2013年5月17日 星期五

[Linux] 檔名相關指令

[Linux] 檔名相關指令

取得檔案(相對路徑)的絕對路徑:

readlink -f dir/to/file

ex

float@dorm:~/float-blog$ readlink -f ~/float-blog/linux_file_name_command.rst
/home/float/float-blog/linux_file_name_command.rst

取得檔案所在目錄:

dirnam dir/to/file

ex

float@dorm:~/float-blog$ dirname ~/float-blog/linux_file_name_command.rst
/home/float/float-blog

取得檔案名稱:

basename dir/to/file

ex

float@dorm:~/float-blog$ basename ~/float-blog/linux_file_name_command.rst
linux_file_name_command.rst

2013年4月26日 星期五

[Python] 使用 sympy 解聯立方程組

使用 sympy 解聯立方程組

4x + 3y + 3z = 350

4x + 2y + 5z = 360

8x + 8y + 10z = 840

from sympy import *

x = Symbol('x')
y = Symbol('y')
z = Symbol('z')

f1 = 4*x + 3*y + 3*z - 350
f2 = 4*x + 2*y + 5*z - 360
f3 = 8*x + 8*y + 10*z - 840

sol = solve((f1, f2, f3), x, y, z)
pprint(sol)
# OUT: {x: 50, y: 30, z: 20}

使用 evalf 將分數轉為小數輸出

ex.

4x2 + 5x - 6 = 0

from sympy import *
x = Symbol('x')
f = 4*x**2 + 5*x -6
sol = solve(f, x)
pprint(sol)
# OUT: [-2, 3/4]
print sol[1].evalf()
# OUT: 0.750000000000000

2013年3月13日 星期三

[shell] 大量取代檔案中關鍵字

大量取代檔案中關鍵字

github 的時候突然發現可以改 username,

之前被 jserv 嫌帳號太難記就索性換掉,

換完才想到 blog 的圖都放在上面阿 Orz,

部落格上面的就複製下來取代掉,原始檔的部份當然就交給指令來取代:

grep a13524000 * | cut -d ':' -f 1 | uniq | xargs sed -i 's/a13524000/float-tw/g'

先用 grep 找到有關鍵字的檔案,再用 cut 切出檔名,用 uniq 去除重複的,

最後用 xargs 餵給 sed 做取代

2013年2月3日 星期日

[PC^2] special judge

[PC2] special judge

剛辦完 ACmarathon 剛好研究了 pc2 的 special judge 怎麼設定

所使用的 pc2 版本是 9.2.3 系統是 Ubuntu 12.04 LTS

首先需要設定的是題目所使用的 Validator 也就是 judge 的程式

通常如果不用 special judge 的話可以使用 pc: sup:2 的 Validator

那 special judge 的話就選用 External Validator

https://github.com/float-tw/float-blog/raw/master/img/pc2_validator_setting.jpeg

然後按 Validator Prog... 後面選擇 judge 的程式,可以是現成的某個程式 (diff...)

也可以自己寫,第二個部份就是 Validator Command Line

這邊是設定如何去執行這個 Validator 這邊有提供五個變數可以使用

{:validator} judge 程式的名稱,也就是前面選擇的程式(不包含路徑)

{:infile} input file,input 測資的檔名

{:outfile} outpu file,參賽者程式接受 input 後的 output

{:ansfile} 從 pc2 設定的答案檔名

{:resfile} 必須輸出的 judge 結果(是個 xml file)

先舉個例子,如果你所選擇的 judge 程式叫做 sp 然後你的 Validator Command Line 這樣寫:

./{:validator} {:infile} {:outfile} {:ansfile} {:resfile}

那執行 judge 的時候就會這樣執行:

./sp input outpu ans result

當然如果你的 judge 程式是用 java, python 寫的也可以這樣寫:

java {:validator} {:infile} {:outfile} {:ansfile} {:resfile}

python {:validator} {:infile} {:outfile} {:ansfile} {:resfile}

當然這些參數的順序是可以任意變動的,如果不需要某些檔案也可以不寫

執行時檔案都會被放在同一個目錄下,像是 pc2-9.2.3/bin/executesite1judge1

當你的 judge 程式執行完後必須依照所給定的 resfile 檔名產生一個檔案

這個檔案的內容大概是這樣:

<?xml version="1.0"?>
<result outcome =  "No - Wrong Answer" security = "132XRSAM.txt">Answer and output file different at line  1</result>

這是一個 WA 的範例,首先第一行就是 xml 的 tag

接著第二行是一個 result tag 裡面包含 outcome 和 security

outcome 就是 judge 的結果,pc2 會去比對在 Judgements 裡面所設定的結果來回應給 client

預設包含這幾種結果:

Yes
No - Compilation Error
No - Run-time Error
No - Time-limit Exceeded
No - Wrong Answer
No - Excessive Output
No - Output Format Error
No - Other - Contact Staff

如果 result file 沒有被正確產生,或是比對不到一樣的結果則會回應 "Undetermined"

security 則是 resfile 的檔案名稱(猜測應該是為了防止上傳可以產生 result file 的程式用的)

tag 裡面的字串並不會被 pc2 拿來使用,可以是一些錯誤的原因之類的

而如果 AC 的話 outcome 的文字可以使用 "Yes" 或 "accepted" 下面是一個 AC 的範例:

<?xml version="1.0"?>
<result outcome =  "accepted" security = "561XRSAM.txt"></result>

另外如果檔案有被產生,而 xml 格式有錯誤(像是少了 security)則狀態會留在 NEW 而 client 也不會收到結果

如果有這樣的問題可以檢查一下(這個問題弄了超久 Orz)

2013年1月12日 星期六

[Linux] 與藍牙裝置建立 spp 連線

首先將電腦與藍牙裝置進行配對

接著使用以下指令之一取得電腦之 BD Address:

$ hciconfig -a
or
$ hciconfig dev
or
$ hcitool dev

例:
┌[float@float-X220]:~
└─$ hcitool dev
Devices:
        hci0    40:2C:F4:E3:14:31

以我自己為例就是 40:2C:F4:E3:14:31

然後取得藍牙裝置的 BD Address:

$ hcitool scan

例:
┌[float@float-X220]:~
└─$ hcitool scan
Scanning ...
        98:E7:9A:08:52:96   float-XT535

這邊是 98:E7:9A:08:52:96

再來建立虛擬序列埠裝置:

$ sudo mknod /dev/rfcomm0 c 216 1
$ sudo chmod 666 /dev/rfcomm0

修改 /etc/bluetooth/rfcomm.conf 為其建立設定:

$ sudo vim /etc/bluetooth/rfcomm.conf

rfcomm0{
    bind no;                    //設置是否自動綁定設備
    device 40:2C:F4:E3:14:31;   //設定綁定設備的BD Address(電腦)
    channel 1;                  //設定設備通道
    comment "BTM";              //對設備的描述
}

添加 SPP(Serial Port Profile) 的SDP協議通道:

$ sudo sdptool add --channel=1 SP

將虛擬序列埠與藍牙裝置綁定:

$ sudo rfcomm bind /dev/rfcomm0 98:E7:9A:08:52:96 1

連接:

$ sudo hcitool cc 98:E7:9A:08:52:96

接著就可以使用可以連接序列埠的程式進行連線,像是 picocom 或 minicom

這邊推薦 picocom 因為我覺得比起 minicom 他的操作簡單許多:

$ picocom /dev/rfcomm0

離開方式為 ^a ^x  (ctrl+a ctrl+x)