Tag Archives: python

在 MacPorts 上裝 pyenv...

因為先前從 Homebrew 跳到 MacPorts 了,剛好有機會重新弄 pyenv,結果發現要解決的問題不少...

第一個遇到的是需要的 library 抓不到的問題,找了官方說明「Common build problems」後知道要自己加上一些環境變數讓 compiler 抓。

解決之後發現 pyenv 會自己編一個 openssl 版本給 Python 用,不會裝到系統內,但是又會因為 /usr/local/opt/ 寫不進去而失敗,所以給他一個可以寫入的目錄。

接下來是 zlib 的路徑也不在前面設定的目錄裡而抓不到,所以得想辦法再找出來塞到環境變數內... 也就是「Install failed, "zlib not available" on macOS Mojave #1219」這篇給的方法。

最後是這樣:

sudo mkdir /usr/local/opt; sudo chown "$(id -u):$(id -g)" /usr/local/opt
LDFLAGS="-L/usr/local/opt/openssl/lib" CPPFLAGS="-I/usr/local/opt/openssl/include" CFLAGS="-I/usr/local/opt/openssl/include -I$(xcrun --show-sdk-path)/usr/include" pyenv install 3.7.3

裝完後可以發現 /usr/local/opt/ 裡面沒有檔案 (但生了幾個空的目錄出來),但總算是裝起來了...

Python 上取代「printf 大法」的工具

「printf 大法」大概是最早期學到的 debug 方式?不同語言有不同的指令,在 Python 裡對應的是 print 指令 (加上 % 或是 .format())。

剛剛看到「cool-RR/pysnooper」這個 Python 上的工具,只要增加 @pysnooper.snoop() 這組 decorator,就可以自動幫你把變數的值印出來。網站上的範例是這樣,可以看到就只是加了一行 decorator:

import pysnooper

@pysnooper.snoop()
def number_to_bits(number):
    if number:
        bits = []
        while number:
            number, remainder = divmod(number, 2)
            bits.insert(0, remainder)
        return bits
    else:
        return [0]

number_to_bits(6)

然後對應的 stderr 就有滿滿的資訊可以看:

Starting var:.. number = 6
21:14:32.099769 call         3 @pysnooper.snoop()
21:14:32.099769 line         5     if number:
21:14:32.099769 line         6         bits = []
New var:....... bits = []
21:14:32.099769 line         7         while number:
21:14:32.099769 line         8             number, remainder = divmod(number, 2)
New var:....... remainder = 0
Modified var:.. number = 3
21:14:32.099769 line         9             bits.insert(0, remainder)
Modified var:.. bits = [0]
21:14:32.099769 line         7         while number:
21:14:32.099769 line         8             number, remainder = divmod(number, 2)
Modified var:.. number = 1
Modified var:.. remainder = 1
21:14:32.099769 line         9             bits.insert(0, remainder)
Modified var:.. bits = [1, 0]
21:14:32.099769 line         7         while number:
21:14:32.099769 line         8             number, remainder = divmod(number, 2)
Modified var:.. number = 0
21:14:32.099769 line         9             bits.insert(0, remainder)
Modified var:.. bits = [1, 1, 0]
21:14:32.099769 line         7         while number:
21:14:32.099769 line        10         return bits
21:14:32.099769 return      10         return bits

另外還可以寫到檔案裡、允許的深度,或是值接指定要哪些變數,另外輸出時也可以指定 prefix 避免混淆 (通常會用在 stderr 不只有 pysnooper 在輸出時)。

用 jiracli 做一些基本常見的操作

公司用 Jira 在管理事情,但眾所皆知的是 Jira 的速度實在太慢 (而且沒改善過),只好找些工具來避免使用 web interface...

翻了 GitHub 後看到 toabctl/jiracli 這個用 Python 開發的軟體,可以在 command line 上對 Jira 做些簡單常見的操作 (對我最主要是 issue 與 comment 的操作),另外工具也支援使用 JQL 搜尋,所以可以透過工具拉下來後再用 grep 或是 awk 過濾...

比較需要注意的是,在第一次執行需要設定的三個參數中,password 的部分其實應該使用 API token (我這邊是 Google SSO,所以不確定一般帳號能不能用自己的密碼登入),這個部分可以在個人設定頁面裡面產生 API token。

設定檔會在 ~/.jiracli.ini 裡面,程式應該會設為 0600,不過可以檢查一下就是了...

自動校正字幕時間的軟體 subsync

看到用 Python 寫的「smacke/subsync」這個軟體,可以自動校正字幕時間:

Language-agnostic automatic synchronization of subtitles to video, so that subtitles are aligned to the correct starting point within the video.

他把上面這個變成下面這個:

因為不是用 machine learning 所以速度意外的快。演算法是對影片本身產生一個 array,然後對字幕也產生 array,最後對兩個 array 用個簡單的公式校準:

  • Discretize video and subtitles by time into 10ms windows.
  • For each 10ms window, determine whether that window contains speech. This is trivial to do for subtitles (we just determine whether any subtitle is "on" during each time window); for video, use an off-the-shelf voice activity detector (VAD) like the one built into webrtc.
  • Now we have two binary strings: one for the subtitles, and one for the video. Try to align these strings by matching 0's with 0's and 1's with 1's. We score these alignments as (# matching digits) - (# mismatched digits).

就這樣解決問題 XD

Python 上觀察 Memory Leak

Zendesk 的「Hunting for Memory Leaks in Python applications」這篇介紹了 memory_profiler 這個工具,可以比較長期的觀察記憶體使用量的問題。

首先是先看正常與疑似異常的分析:

然後可以拉出資料型態資訊:

這些資訊要找 memory leak 還是蠻粗糙的,但算是給了個方向,而且用起來算是簡單...

SQLite 的 CLI 操作工具 litecli

之前應該都是用 SQLite 提供的 cli 操作,現在有人提供支援 auto completion 與顏色的 cli 軟體了:「CLI for SQLite Databases with auto-completion and syntax highlighting」。

工具是用 Python 寫的,可以直接用 pip 安裝。

用 Py-Spy 分析 Python 程式效率

這之後應該會變成 Python community 的神器之一...

剛剛看到分析 Python 程式效率的工具,只要有 pid 或是直接包著跑就可以分析:「Py-Spy: A sampling profiler for Python programs.」,執行起來長這樣:

而且還可以直接產生火焰圖讓開發者直接確認,超友善:

在 FAQ 的地方也有提到作者開發這套軟體的原因。有些在開發環境根本看不出問題的,可以很快的透過這個工具在 production 上看:

This project aims to let you profile and debug any running Python program, even if the program is serving production traffic.

另外一個重點在於其他常見的 profiling 工具通常都要改程式引用進來使用,這通常會使得程式效率慢下來,而 Pyflame 支援的平台比較少:

While there are many other python profiling projects, almost all of them require modifying the profiled program in some way. Usually, the profiling code runs inside of the target python process, which will slow down and change how the program operates. This means it's not generally safe to use these profilers for debugging issues in production services since they will usually have a noticeable impact on performance. The only other Python profiler that runs totally in a separate process is pyflame, which profiles remote python processes by using the ptrace system call. While pyflame is a great project, it doesn't support Python 3.7 yet and doesn't work on OSX or Windows.

Python 3 內建的 lru_cache...

Twitter 上看到 Python 3 內建的 lru_cache()

從文件上可以看到預設值是 128 個:

@functools.lru_cache(maxsize=128, typed=False)

tweet 裡面有討論到 memory leak 的問題可以看一下,不過如果是拿來寫工具的話,應該不會有什麼問題...