pipdeptree

前幾天上傳程式到 openshift 時,發現新版的 six 安裝不上去,原因是 OpenShift 所帶的 six 是 0.3 版,但是無法透過 sudo 等之類的方式來安裝新版,所以想查到底是哪個模組會需要用到新版的 six。上網找了一下,發現 pipdeptree 可以滿足我的需求。

用 pip install pipdeptree 就可以安裝,使用上也很簡單,輸入 pipdeptree 就會列出各個模組的相依性與其所需最低版本。

結果大致是這樣:

Warning!!! Possibly conflicting dependencies found:
* HaodooScraper-Flask==1.0
 - python-dateutil [required: ==2.3, installed: 2.6.0]
 - six [required: ==1.3.0, installed: 1.10.0]
------------------------------------------------------------------------
alembic==0.6.7
  - Mako [required: Any, installed: 1.0.0]
    - MarkupSafe [required: >=0.9.2, installed: 0.23]
  - SQLAlchemy [required: >=0.7.3, installed: 0.9.8]
cssselect==0.9.1
Flask-APIBlueprint==1.0.0
  - flask [required: >=0.11.1,<1.0, installed: 0.12] - click [required: >=2.0, installed: 6.7]
    - itsdangerous [required: >=0.21, installed: 0.24]
    - Jinja2 [required: >=2.4, installed: 2.9.5]
      - MarkupSafe [required: >=0.23, installed: 0.23]
    - Werkzeug [required: >=0.7, installed: 0.12.1]
  - six [required: <2.0,>=1.10.0, installed: 1.10.0]
HaodooScraper-Flask==1.0
  - Flask [required: Any, installed: 0.12]
    - click [required: >=2.0, installed: 6.7]
    - itsdangerous [required: >=0.21, installed: 0.24]
    - Jinja2 [required: >=2.4, installed: 2.9.5]
      - MarkupSafe [required: >=0.23, installed: 0.23]
    - Werkzeug [required: >=0.7, installed: 0.12.1]
  - Flask-Bootstrap [required: Any, installed: 3.3.7.1]
    - dominate [required: Any, installed: 2.3.1]
    - Flask [required: >=0.8, installed: 0.12]
      - click [required: >=2.0, installed: 6.7]
      - itsdangerous [required: >=0.21, installed: 0.24]
      - Jinja2 [required: >=2.4, installed: 2.9.5]
        - MarkupSafe [required: >=0.23, installed: 0.23]
      - Werkzeug [required: >=0.7, installed: 0.12.1]
    - visitor [required: Any, installed: 0.1.3]
  - Flask-JsonTools [required: Any, installed: 0.1.1.post0]
    - flask [required: >=0.10.1, installed: 0.12]
      - click [required: >=2.0, installed: 6.7]
      - itsdangerous [required: >=0.21, installed: 0.24]
      - Jinja2 [required: >=2.4, installed: 2.9.5]
        - MarkupSafe [required: >=0.23, installed: 0.23]
      - Werkzeug [required: >=0.7, installed: 0.12.1]
  - flask-restplus [required: Any, installed: 0.10.1]
    - aniso8601 [required: >=0.82, installed: 1.2.0]
      - python-dateutil [required: Any, installed: 2.6.0]
        - six [required: >=1.5, installed: 1.10.0]
    - Flask [required: >=0.8, installed: 0.12]
      - click [required: >=2.0, installed: 6.7]
      - itsdangerous [required: >=0.21, installed: 0.24]
      - Jinja2 [required: >=2.4, installed: 2.9.5]
        - MarkupSafe [required: >=0.23, installed: 0.23]
      - Werkzeug [required: >=0.7, installed: 0.12.1]
    - jsonschema [required: Any, installed: 2.6.0]
    - pytz [required: Any, installed: 2017.2]
    - six [required: >=1.3.0, installed: 1.10.0]
  - Flask-WTF [required: Any, installed: 0.14.2]
    - Flask [required: Any, installed: 0.12]
      - click [required: >=2.0, installed: 6.7]
      - itsdangerous [required: >=0.21, installed: 0.24]
      - Jinja2 [required: >=2.4, installed: 2.9.5]
        - MarkupSafe [required: >=0.23, installed: 0.23]
      - Werkzeug [required: >=0.7, installed: 0.12.1]
    - WTForms [required: Any, installed: 2.1]
  - lxml [required: Any, installed: 3.4.0]
  - python-dateutil [required: ==2.3, installed: 2.6.0]
    - six [required: >=1.5, installed: 1.10.0]
  - requests [required: Any, installed: 2.13.0]
  - six [required: ==1.3.0, installed: 1.10.0]
  - SQLAlchemy [required: Any, installed: 0.9.8]
nose==1.2.1
pipdeptree==0.10.1
  - pip [required: >=6.0.0, installed: 9.0.1]
pkg-resources==0.0.0
PyMySQL==0.6.2
pyOpenSSL==0.14
  - cryptography [required: >=0.2.1, installed: 1.8.1]
    - asn1crypto [required: >=0.21.0, installed: 0.22.0]
    - cffi [required: >=1.4.1, installed: 1.10.0]
      - pycparser [required: Any, installed: 2.17]
    - idna [required: >=2.1, installed: 2.5]
    - packaging [required: Any, installed: 16.8]
      - pyparsing [required: Any, installed: 2.2.0]
      - six [required: Any, installed: 1.10.0]
    - setuptools [required: >=11.3, installed: 34.3.3]
      - appdirs [required: >=1.4.0, installed: 1.4.3]
      - packaging [required: >=16.8, installed: 16.8]
        - pyparsing [required: Any, installed: 2.2.0]
        - six [required: Any, installed: 1.10.0]
      - six [required: >=1.6.0, installed: 1.10.0]
    - six [required: >=1.4.1, installed: 1.10.0]
  - six [required: >=1.5.2, installed: 1.10.0]
wheel==0.30.0a0

Django queryset 對日期時間欄位的額外設定

Django queryset 對日期時間的處理已經很完備了,可以透過使用 __year 或 __month 等方式來找到是某年或某月的紀錄。

這兩天碰到的狀況是,資料是 MySQL 時,日期時間的比對 (__year / __month) 失效了。仔細看過文件以後,才發現 MySQL 需要事先設定,使用 mysql_tzinfo_to_sql 載入時區表格才行。

This function performs time zone conversions directly in the database. As a consequence, your database must be able to interpret the value of tzinfo.tzname(None). This translates into the following requirements:

在終端機 (shell) 裡,輸入下列指令:

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql

接著重新啟動 MySQL 伺服器即可。

mysql_tzinfo_to_sql 的用法不只一種,我選擇的是最簡單的用法。

Amazon Cloud drive on Ubuntu

安裝 acd_cli 就可以了。

安裝跟使用可以參閱 https://acd-cli.readthedocs.io/en/latest/ ,用 pip3 install
git+https://github.com/yadayada/acd_cli.git 就安裝完了。不想裝到系統 /usr/local 的話,加上 –user,可以裝到 $HOME/.local 裡。

第一次使用要先 acd_cli sync,之後就可以使用上傳等功能了,最方便的是,acd_cli 可以利用 FUSE 掛載在某個資料夾下,這樣就可以用檔案總管或是 rsync 一類的軟體來處理了。

參考資料:

docker-compose.yml 裡的相依性與啟動順序

簡單的說,depends_on 跟 links 只保證相依的 container 有啟動,但不保證裏面的服務已經啟動完畢,可以接受服務了。

我找到的解決方法,是利用 wait-for-it 這個 bash script 來測試 container 的 port 是否開啟。docker-compose v3 好像有要試圖解決這問題,不過還沒正式釋出。也是有一些其他的解法,不過,我覺得不是很直覺,就先放著了。

參考資料:

 

電影流水帳(2017/3/2~2017/3/19)

白歆惠-裸白歆惠,知名的模特兒,後來轉戲劇,演了不少連續劇跟電影,是銷售奇姬的女主角。

  • 一萬公里的約定 (IMDB, Wikipedia)。這片真的…不好看。劇情太破碎,是可以猜到為什麼,但是這樣說故事實在是讓人看不下去。結局也交代的不好,看起來育幼院是募到資金了,但是以晴去密醫那兒開心以後怎麼了?哥哥呢?為什麼要送以晴去作換心手術,那自己的妻兒是不用管了喔?純粹的灑狗血。
    故事是描述弟弟立志參加超級馬拉松的過程。兄弟倆的父親是跳遠選手,但是後來卻只能落魄的過日子。哥哥逃家去外地唸書、練馬拉松,弟弟後來也跟著去了,對,他們就這樣把老父丟在家裡。弟弟在哥哥那邊遇到了助理教練以晴,接受她的訓練,而且日久生情。哥哥則是讓女友未婚懷孕,為了要賺錢養孩子,跑去運毒。後來,弟弟因為以晴走了,就停止練習跑超馬,哥哥則繼續運毒。弟弟為了生活,跑去開計程車,遇到周杰倫,這段還蠻勵志的。然後跑去阻止哥哥,之後又莫名其妙的幫起哥哥運毒。總之,過了一陣子,弟弟某天遇到以晴,知道以晴的病情,決定重新開始認真跑超馬,並且變得有名起來。最後,則是哥哥為了讓以晴,推去找密醫換心,弟弟則是成功募到育幼院款項,完成以晴心願,大概就這樣。
  • 超級快遞 (IMDB, Wikipedia)。中韓合作的電影,女主角是 Running Man 的宋智孝,宋智孝在裏面飾演一個保安主任,實則是一個偷兒,電影的節奏緊湊,還不錯。
    陳赫飾演快遞員馬力,原來是個賽車手,後來因故改當快遞員。他有個女友娜娜,已經論及婚嫁。某天他送貨到王三表家時,遇到美熙,他感到奇怪,明明應該是王三表出來的,卻是美熙。不過還是讓她簽收了,就在要離開時,遇到 Gary 來追討快遞的物品,因而捲入這樁怪事。
    後來透過美熙才知道,原來美熙是保安主任,Gary 從博物館裡偷走,美熙則是追著這個古物來到這裡。經過幾番與 Gary 的爭奪,馬力幫美熙取回古物,可是卻意外翻盤,美熙居然也是一個偷兒。Gary 後來挾持了馬力的女友,要馬力拿古物來換,可是美熙已經到了機場,準備要走,馬力發了訊息,決定單槍匹馬去救人。最後,美熙仍是心軟,回來幫了馬力,救回馬力的女友,古物也歸還,皆大歡喜。
  • 銷售奇姬 (IMDB, Wikipedia)。最近衛視電影台開始放送的電影,跟電視購物有關係的故事。
    陳夙芬‬因為失業變得很失意,好不容易找到一份在賣場銷售的工作,可是卻因為拉不下臉而再次面臨失業的危險。在潔哥要找蘿絲復仇的陰錯陽差之下,夙芬變成潔哥的弟子,銷售技巧在潔哥指導之下,脫胎換骨,而且因為原本首席的美秀離職,成為賣場的首席。
    夙芬騎驢找馬,去電視購物公司面試,卻巧遇美秀。兩人在電視購物公司總經理的賞識下,進去上班。美秀對於夙芬始終抱有敵意,一直覺得夙芬並不尊重銷售的工作。夙芬則是誤打誤撞,慢慢闖出一番局面。不過職場順利,就忽略了家裡。夙芬的老公智凱為了讓夙芬離開購物公司,找了之前意外遇到的蘿絲幫忙,讓她去破壞夙芬的事業,卻意外讓夙芬愈來愈好。
    嗯,從這邊到結局,我沒看到,因為被迫要離開。結局大致上就是夙芬離開購物公司,回到家裡,而潔哥與蘿絲重歸舊好,美秀也拋開了對夙芬的敵意,皆大歡喜。
  • Tropic Thunder (IMDB, Wikipedia),台譯:開麥拉驚魂。這部電影以前看過一次了,再重看。
    前面的片頭非常有趣,大致上是介紹電影裡主角們之前的豐功偉業,但是他們都過了巔峰的時候,開始走下坡,大家想靠這部電影重新走紅。導演是個名不見經傳的新導演,沒辦法駕馭這幾個演員,於是聽信劇本原著的意見,將這些人帶到真實的叢林裡去,進行真槍實彈的拍片。
    一行人在叢林裡遇到真正的毒梟,導演誤踩地雷先掛了,其他演員則認為是導演故意的,就照著劇本在叢林裡穿梭、拍戲。到了後來,演員們發現了自己真的被困在叢林裡,並且必須面對兇狠的毒梟。特效組則跟劇本原著去叢林救人,卻意外發現劇本原著是騙子,劇本故事也是假的,兩人後來被毒梟抓走。
    Tugg 也被毒梟捉走,但因為毒梟們很喜歡 Simple jack 這部電影,而放過 Tugg,只要求他持續演出 Jack 這個角色。一行人為了救出 Tugg ,就計劃了行動,進入毒梟村落救人。最終所有人都逃脫出來,原本 Tugg 還在猶豫要不要留在毒梟村落裡扮演 Simple jack ,但村民遠超乎 Tugg 想像之外,Tugg 當下就決定回去了。
    電影裡很多大牌以出人意料的方式演出,像是 Robert Downey Jr., Tom Cruise, Matthew McConaughey 等,片尾 Tom Cruise 的熱舞真的是經典了。
  • 行運超人 (IMDB, Wikipedia)。很久以前看的電影,發現自己沒紀錄。故事一開始先帶出為什麼葉孤紅那麼倒楣的原因,然後帶出葉孤紅去找賴料布改變自身命運並找到如意郎君的經過。蠻輕鬆有趣的故事,可以打發掉不少時間。今年看歌手2017時,意外發現原來演葉太的杜麗莎居然是個唱歌的老前輩,教過不少歌手唱歌,也在發現原來楊千嬅跟鄭中基有過一段情。

 

docker-machine 的 port forwarding

最近在 Windows 試 docker-toolbox,想讓外部連線連到 host 時,其實是連接到 在 VM 裡服務的 docker container,所以查了看怎麼做。

結果比想像中還要簡單,就是利用 vboxmanage controlvm 去設定 port forwarding 就可以了。

/c/Program\ Files/Oracle/VirtualBox/VBoxManage.exe controlvm vm_name natpf1 "rule1,tcp,,80,,80"

那要刪除掉這條 port forwarding 的規則,用

/c/Program\ Files/Oracle/VirtualBox/VBoxManage.exe controlvm vm_name natpf1 delete rule1

即可。

那在 linux 下也可以用同樣的方式來做 port forwarding,唯一的限制是非 root 用戶,沒辦法做 port 1024 以下的 port forwarding。

說明:

  • docker-toolbox 其實是把 docker, docker-machine, docker-compose, virtualbox 等工具包裝起來的一個便捷安裝包
  • vm_name 可以用 vboxmanage list vms 取得
  • 也可以開啟 VirtualBox ,在左側選到虛擬機,再進設定去改動。

參考資料:

mypy

演講:https://youtu.be/ZP_QV4ccFHQ

mypy 是靜態型別檢查工具,遵循 PEP484 與 PEP526 這兩個標準

而 PEP484 與 PEP526 這兩個標準最主要的用途是為 Python 加上型別標示,這樣可以更容易找到潛在的錯誤。

安裝

pip3 install mypy-lang

程式的部份 (type annotation)

Python 3

def hello(name: str) -> str:
    """foo."""
    return "Hello, {}".format(name)


def main() -> None:
    """Main entry."""
    hello("John")

Python 2

def hello(name):
    # type: (str) -> str
    """foo."""
    return "Hello, {}".format(name)


def main():
    # type: () -> None
    """Main entry."""
    hello("John")

如何使用 mypy 檢查

如果程式沒加 type annotation,那麼執行 mypy 不會有任何問題。 如果有一部份使用了 type annotation,那麼執行 mypy 就會告知有問題。 要強制檢查,可以使用 –disallow-untyped-defs

mypy --disallow-untyped-defs your_program.py

要產生 HTML 報告

mkdir html
mypy --html-report ./html your_program.py
xdg-open ./html/index.html

產生 JUnit XML

mypy --junit-xml JUNIT_XML your_program.py

案例

Dropbox 內部已經在使用。

電影流水帳(2017/2/18~2017/3/1)

2013 Imagen Foundation Awards, Natalie Martinez
Natalie Martinez 是 Death Race 的女主角,超正的。

  • Death Race (IMDB, Wikipedia),台譯:絕命尬車。場面浩大的飆車鏡頭,讓人血脈僨張。
    時間點設定在一個類似末世的未來,監獄被大型財團控制,並利用囚犯想逃出去的慾望來進行死亡賽車。Jensen 被裁員,回到家上樓梳洗完下來,發現妻子倒在血泊中,接著有人打昏他,將現場狀況處理成是 Jensen 殺的樣子。Jensen 因此入獄,在監獄裡,他被徵召去冒充已經勝利四次的 Frankenstein 參加賽車,與 Coach 的裝修汽車小組合作。在參加賽車的過程中,他慢慢搞清楚一切都是典獄長在操控,於是 Jensen 反過來和對手 Joe 串謀設局,讓典獄長以為他們倆要拼個你死我活,結果卻是轟開賽車場圍牆逃出去。最後 Coach 引爆典獄長原本要炸死 Jensen 的炸藥炸死典獄長等人。
  • Paul (IMDB, Wikipedia),台譯:我們撞到外星人。看到主角是 Simon Pegg 就決定把電影看完了,邊看的過程發現這部電影除了 Simon Pegg 跟他的老搭檔 Nick Frost (胖胖的那個) 之外,還有 Seth Rogen 幫那個外星人配音,以及冷面笑匠 Jason Bateman 。電影的故事算是公路電影,主角們到最後都放下了一些心結。
    Graeme 跟 Clive 是好朋友,他們一起去美國玩,並參加科幻展。在結束科幻展的路上,他們遇到了在逃走的 Paul ,一個外星人,從不接受它到變成好朋友,一起在公路旅行。在公路上 Graeme 遇到真命天女 Ruth ,相互喜歡上,而 Paul 治癒了 Ruth 的眼睛。追著 Paul 的警探緊追著他們,想要抓到 Paul ,Ruth 的父親也為了愛女而追著他們,在路上發生了許多事情。到了公路的終點,警探的老闆 (Sigourney Weaver 飾演) 出馬,這時才揭露出,追著 Paul 的 Lorenzo Zoil 是好人,其實是要保護 Paul ,而警探的老闆追著 Paul 是想利用他,最後 Graeme 幫 Paul 檔了子彈,來接 Paul 的太空船降落時幹掉警探的老闆,這時眼看 Graeme 就要死了,Paul 使用了超能力救活 Graeme ,Paul 跟眾人告別,搭著太空船回去,而 Graeme 等人,也繼續自己的人生,完成一個皆大歡喜的收尾。
  • John Wick (IMDB, Wikipedia),台譯:捍衛任務。看到 John Wick 的影評,才決定要看的。看完以後,覺得還不賴。
    John Wick 面臨喪妻之痛,在萬念俱灰的時候,收到一隻小狗,原來是妻子在死前準備好的禮物,John Wick 因為這隻狗而重燃希望。可是某天開車出去時,碰到幫派老大兒子,他覺得車子很酷,想買,可是 John Wick 不鳥他,當天晚上,John Wick 就被襲擊了,狗也被殺了。John Wick 非常的憤怒,於是決定復仇。幫派老大知道了這件事情,教訓了兒子,想跟 John Wick 和解,可是講不通。幫派老大只好派出殺手來追殺 John Wick ,John Wick 一一化解,並且展開殺戮,將整個幫派滅了。最後 John Wick 受了重傷回去,在回去路上還特地去動物收容所收養了一隻狗,電影就這樣落幕。
  • The Amazing Spider-Man 2 (IMDB, Wikipedia),台譯:蜘蛛人-驚奇再起2-電光之戰。這部電影其實在有線電視頻道看了兩三次了,這次終於完整看完。場面還可以,最可惜的就是 Emma Stone 飾演的 Gwen 被賜死了,那後面就沒什麼好演的了啊!!! 還留什麼 Harry 在監獄策劃的梗?
    一開始交代了 Peter 父母與 Osborn 公司的愛恨情仇,兩人是為了避免 Osborn 將他們的研究拿去做軍事用途而決定帶著研究成果逃走,然後在逃亡途中墜機身亡,一眨眼就過了十年。
    Peter 雖然跟 Gwen 在熱練,但他始終難以忘懷 Gwen 老爸要他不要將 Gwen 牽扯到危險之中,所以他最終忍痛與 Gwen 分手。Electro 原本是 Osborn 的電力工程師 Max,但一直都不被看重,某次在街上被蜘蛛人搭救而瘋狂喜歡上蜘蛛人。在意外中,Max 變成了 Electro。Harry 是 Peter 幼時的摯友,但身上有著 Osborn 家族的詛咒 – 一種奇怪的病症,父親致力於研究忽略 Harry 就是為了要讓家族能從這個詛咒解脫出來。
    Harry 在父親死後,為了想讓自己擺脫詛咒而想取得 Peter 的血。在公司被外人奪走之後,他找了 Electro 幫忙,到地下室取得螫到 Peter 的蜘蛛血清,注射到自己身上,血清似乎治癒了身上的詛咒,卻變成了 Green Goblin。Electro 跟前來阻止的蜘蛛人 Peter 打了起來,Gwen 隨後趕來幫忙,總算是阻止了 Electro。但之後的 Green Goblin 就沒那麼容易對付了,一場混戰之下,Peter 雖然阻止了 Green Goblin ,但沒能救到 Gwen。之後,Peter 消沉了很久一段時間,經過沈澱以後,他看到 Gwen 的演說,決定重新振作起來。片子就在 Green Goblin 沒死,Peter 正要阻止 Rhino 的場面下結束。
  • 雙瞳 (IMDB, Wikipedia)。IMDB 上放的電影海報沒什麼張力,我還是比較喜歡維基百科上放的那張,比較有驚悚感。我滿喜歡這部電影的,既驚悚但又不失溫暖。現在回頭看裡面不少擔任配角的演員在當時名不經傳,但現在都已經各據一方了。
    台灣連續發生幾起奇怪的死亡事件,死因都是吸入了奇妙的黴菌而導致意想不到的死亡。警方沒辦法解決,於是找了美國 FBI 來幫忙查案。警局派了黃火土當作跟 FBI 的窗口,黃火土跟 Kevin 一起進行查案,愈查愈覺得不對勁。在查案的同時,黃火土也困在妻子要跟他離婚與女兒美美因為之前被妻舅挾持而無法說話的家庭事件裡。案子查到最後,找到了深藏於科技公司的寺廟,廟裡的光頭涉嫌擄人等罪嫌,這樣看來,似乎已經結案了,但是矛頭隱隱指向看似無辜的謝亞理身上。既然案子似乎已經結案,Kevin 要回去美國,在回國的最後一晚,與黃火土一家吃晚飯。吃完晚飯的隔天,Kevin 被發現死在黃火土家的客廳沙發上,而火土也被發現吸入了這黴菌,緊急送醫。送到醫院以後,火土被救回,後來他醒了以後,跑去找謝亞理。在廟裡,謝亞理緩緩道出事情的前因後果,最終就是要依照成仙的預言,讓火土殺了她,讓她成仙。火土不肯,可是在黴菌的作用下,火土還是殺了謝亞理。警方發現火土不見,趕緊來找人,也因此找到了瀕死的火土,將火土緊急送醫。火土的妻女趕到現場,看到死去的火土,哭喊著要火土回來,女兒這時開口喊了要爸爸回來,而火土也真的因為感動而復活。

電影流水帳(2017/1/12~2017/2/17)

Margot Robbie Margot Elise Robbie ,最有名的角色應該就小丑女了吧~ 那個造型實在太經典。這次在大賣空裡有看到她出來客串說明,所以就選了她的照片。

  • Moana (IMDB, Wikipedia),台譯:海洋奇緣。這是一個風格接近南島語系民族神話的故事,相信故事也是取材自南島語系民族才是,裏面的毛伊畫的就很像是紐西蘭的毛利人。歌曲超級好聽的,中文版是 A-Lin 唱的,非常的有力道。
    電影一開始先帶出持有魔法魚鉤的半神人毛伊的故事,毛伊為了人類,盜取了塔菲緹的心,在要離開的時候,被帖卡打敗,鉤子掉落海底,毛伊被困在小島上。莫娜從小就被海洋眷顧,聽著祖母說這個故事長大,長大以後,她開始質疑為什麼父親不讓族人離開這座島。透過祖母的引導,才知道祖先其實是航海族,但因為毛伊而誕生的黑暗而決定不再外出航海,以免遭遇危險。不過黑暗還是找上門了,在加上祖母的死,莫娜決定外出尋找毛伊,請毛伊找回塔菲緹的心,消滅黑暗。
    莫娜透過海洋的幫忙找到了毛伊,但毛伊是個自大的人,不願意跟莫娜合作。莫娜花了好大的功夫,才讓毛伊願意幫忙。在尋找魔勾跟塔菲緹的心的旅程裡,兩人慢慢敞開心胸,互相信任,互相幫忙。最後要放回塔菲緹的心時,遇到帖卡,毛伊花了好一番功夫引開帖卡,莫娜發現沒地方可放塔菲緹的心,她看著帖卡,突然領悟到,帖卡就是塔菲緹,所以她走向帖卡,將塔菲緹的心交給帖卡。帖卡在這個時候變回了塔菲緹,海洋的黑暗也隨之消失。莫娜告別毛伊、塔菲緹,回到故鄉,整個村子也回歸為航海族的身份。
  • Maidentrip (IMDB, Wikipedia),台譯:處女航。這是一部關於荷蘭小女生的紀錄片,一個十三歲的女生,在歷經十個月的訴訟以後(保護團體要求接管監護權,以阻止小女生進行環球航行的瘋狂舉動),在14歲進行預定兩年,以帆船環遊世界的行動。令人感到佩服的是這小女生十三歲就知道自己要做什麼,而且自己找贊助,擬定計劃,找資料等等,不假父母之手,令人佩服。
  • The Lego Batman Movie (IMDB, Wikipedia),台譯:樂高蝙蝠俠。故事主要是強調伙伴和朋友的重要性。
    大意是蝙蝠俠太自大也怕失去,所以不打算有伙伴,也不認可小丑。小丑在不被蝙蝠俠認同的情況,剛好看到電視訪談超人把某個壞人關掉幽靈空間,就決意進入幽靈空間尋求盟友,於是設了局,讓蝙蝠俠去偷超人的幽靈空間傳送器,將自己送去幽靈空間。
    小丑在幽靈空間裡找到佛地魔、索倫、金剛等曾經在華納電影裡出現過的壞蛋來幫忙,小丑女則算準時煎,奪回傳送器,將裡面的壞蛋都傳送回來破壞高譚市。蝙蝠俠寡不敵眾,得到教訓,學到伙伴和朋友的重要性,於是和阿福、羅賓、高登的女兒(蝙蝠女)等聯手將這些壞蛋送回幽靈空間。但是這並沒有拯救高譚市,城市受到來不及拆的炸彈影響而裂開。蝙蝠俠最後尋求小丑的原諒及幫助而拯救了高譚市。
    笑點不是很好笑,我在看到一半時,差一點點睡著,整體來說我覺得普普,沒有比前作樂高玩電影好看。
  • The big short (IMDB, Wikipedia),台譯:大賣空。有個醫生,也是個基金經理人,在 2006 年研讀了大量的房貸資訊以後,認定與次級房貸相關的金融商品都會泡沫化,所以他大膽的將基金拿去作賣空。許多華爾街的人聽到這消息都當作笑柄,但是有兩三組人聽到這消息,認真的進行求證,確認了這個可能性,也開始賣空。到了 2007、2008 年,次級房貸市場明顯愈來愈危險,但是始終都沒往下掉。在他們資金吃緊的情況下,他們發現政府、評比機構也跟著在作假,所以次級房貸市場還維持著熱絡。不過,到了 2008 年中以後,底層的真實情況終於反映到金融商品上,於是發生了金融海嘯。
    相當警世的一部電影,我對於裏面 Morgan Stanley FrontPoint 的負責人 Steve Eisman 印象深刻,他在聽到次級房貸消息以後,和組員到實際的市場去進行調查與了解,發現房貸市場非常可能會崩盤,才開始進行賣空。最近在看系統思考的書,裏面也提到了同樣的看法,在面對系統前,最好先進行觀察,確定整個系統的流程與各個可能的影響因子,這樣才能找出最好的槓桿點與施力點。想多了解一點關於次級房貸,可以參考 《大賣空》到底在演什麼?簡單搞懂《大賣空》片中的艱澀財經內容!

django-channels websocket 與 nginx

django-channels 的佈署指南,裏面的幾個重點:

  1. 先安裝 redis,再用 pip 安裝 asgi_redis ,然後將 settings 裡 CHANNEL_LAYERS 的 “BACKEND” 改為 asgi_redis.RedisChannelLayer ,這樣效能會比較好些。
  2. 執行 worker :
    python manage.py runworker
  3. 在 wsgi.py 的同個資料夾,新增 asgi.py ,裏面放
    import os
    from channels.asgi import get_channel_layer
    
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_project.settings")
    
    channel_layer = get_channel_layer()
  4. 執行 ASGI server :
    daphne your_project.asgi:channel_layer

    ,daphne 是在安裝 channels 時,會跟著裝上的。使用了 daphne 以後,就可以不需要 gunicorn 了,至於 uwsgi ,因為我沒在用,所以沒有深入研究。

runworker 跟 daphne 的部份,可以使用 supervisor 或者是寫 upstart script ,讓他們自動啟動。除了這些重點以外,nginx 的設定也需要調整,設定不多,只有幾行,這可以參考這兩篇文章:

大致的設定如下:

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

upstream app_server {
    server 127.0.0.1:8000 fail_timeout=0;
}

server {
    include mime.types;
    default_type application/octet-stream;
    access_log /var/log/nginx/access.log combined;
    sendfile on;

    listen 80;
    client_max_body_size 4G;

    # set the correct host(s) for your site
    server_name example.com;

    keepalive_timeout 5;

    # path for static files
    location /static/ {
        alias /srv/app/site/static/;
    }

    location /media/ {
        alias /var/app/media/;
    }

    location / {
        # checks for static file, if not found proxy to app
        try_files $uri @proxy_to_app;
    }

    location @proxy_to_app {
        proxy_buffering off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;

        proxy_pass   http://app_server;

        # For websocket
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }

    error_page 500 502 503 504 /500.html;
    location = /500.html {
        root /srv/app/site/static;
    }
}

我在套用這些設定以後,websocket 仍然無法順利連上,找了好半天,才找到這篇:Websockets fail to work after upgrading to 1.0.0 · Issue #466 · django/channels  ,看完才知道,channels/daphne 在升級到 1.0 以後,程式裡的 websocket consumer 必須要送出

{"accept": True}

才行。這部份可以參考 1.0 的 release note ,也可以參考新的 Getting Start。不過我在參考 Getting start 時,居然沒注意到這行,也是我太大意了。