星期四, 5月 10, 2018

Django 節省記憶體的一些紀錄之二

這篇會順帶提一些提高效能的紀錄。

strftime

datetime.strftime 可以將日期時間格式化為需要的字串,但是,在經過 profiling 以後,我發現呼叫這個函式相當的花時間。在網路上搜尋以後,發現有人在 stackoverflow 上問相似的問題,有人回答說改用 python 的 string format 就可以大大的提高效能。
# 原作法
from datetime import datetime
dt = datetime.now()
dt.strftime("%Y/%m/%d")  # slower
"{:04d}/{:02d}/{:02d}".format(dt.year, dt.month, dt.day)  # Fast!!

JSONEncoder.iterencode

這是在Use StreamingHttpResponse by default for JSON 這個 gist 上看到的,裏面使用了 JSONEncoder.iterencode 搭配 StreamingHTTPResponse 處理。一般來說,在輸出為 JSON 時,都是整個物件或資料丟給 json.dumps(),但這樣在處理大量資料的情況時,其實是有可能佔用大量記憶體的。Python json 模組的 JSONEncoder 提供了 iterencode() 函式,iterncode() 會回傳 generator 回來,之前有提到使用 generator 可以確保在使用到的時候,才將值回傳出來,可以避免佔用過多的記憶體。再加上 StreamingHTTPResponse/HTTPResponse 的 content 都支援使用 generator,這樣就可以節省大量記憶體了。

日期時間時區的轉換

本來我是使用 Arrow 在處理時區的轉換,但是,在 profiling 以後,發現這個步驟會花掉蠻多時間,於是看過 Arrow 的原始碼以後,發現 Arrow 只是使用 python datetime 模組裡面的函式在做,所以將原本時區轉換的部份改寫掉,就大幅提升速度了。

from arrow import Arrow
from dateutil import tz
from django.utils import timezone

dt = timezone.now()  # utc time
new_timezone = tz.gettz('Asia/Taipei')  # get local timezone
new_local_time_1 = Arrow.fromdatetime(dt).to(new_timezone).datetime  # slower
new_local_time_2 = dt.astimezone(new_timezone)  # Fast!!

星期四, 4月 26, 2018

電影流水帳(2018/2/21~2018/4/12)

Karen Gillan Karen Gillan,坦白說,完全看不出來是「星際異攻隊」裡的 Nebula ,本人看起來很清新可人呢~
  • 君の名は (IMDB, Wikipedia),台譯:你的名字。這故事一直讓我想起村上春樹的「百分百女孩」,有種淡淡的哀傷,讓人唏噓不已。
    故事一開始是瀧跟三葉的身體交換了,他們有著默契,努力過著對方的生活。原本以為就是單純的身體交換故事,但在中段出現轉折。瀧在某次約會後,就再也沒有跟三葉交換身體了。瀧覺得很奇怪,就開始進行調查。在調查以後,才了解到原來女孩所在的時空居然是三年前,在那個時間點,女孩所在的糸守町被彗星碎片擊中而滅村。瀧不死心,鍥而不捨的到了宮水神社,透過口嚼酒,再次跟三年前的三葉交換身體。這次的交換,兩人的努力終究改變了時間的流向,讓村莊裡的人們躲過災難。不過,兩人因此失去對方的記憶,經過數年,一直在追尋著似乎存在心裡的對方。電影最後一幕,兩人終於相遇,但是他們真的能相認嗎?沒有答案,這樣也好。若有似無的結局,才會讓人念念不忘。
  • Coco (IMDB, Wikipedia),台譯:可可夜總會。看完以後才知道台灣為什麼會這樣翻譯,Coco 是人名,「夜總會」則是因為台灣大多數的人將墓地稱作「夜總會」,而主角又是去陰間走一趟的關係。故事溫馨、有趣,有 Pixar 一貫的風格,主題曲 Remember me 符合情境,真的是很不錯。
    主角 Miguel 的家庭裡因為喜愛音樂的祖先拋妻棄子出外去追求音樂的夢,所以嚴令禁止子孫傳唱音樂。Miguel 非常喜愛音樂,意外發現的聞名的大歌星 Ernesto 可能就是自己的祖先,在跟家人分享的時候,被家人責罵、阻止。Miguel 生氣的跑到墓地去,想要證實大歌星 Ernesto 就是自己祖先,卻意外進入陰間世界。在陰間,Miguel 遇到了自己的親人,親人們試圖要送 Miguel 回去,但 Miguel 不肯接受以後不玩音樂的條件而賭氣逃走。逃走途中遇到了 Héctor ,Miguel 請求 Héctor 幫忙他找 Ernesto ,Héctor 則請求 Miguel 帶照片回陽間去,於是他們開始互相幫助。在這段過程裡,兩人相互了解,而且意外發現了 Ernesto 其實是個卑鄙的傢伙,他害死 Héctor ,奪取他的創作。更令人意外的是,Héctor 就是 Miguel 那個拋妻棄子的祖先。最後經過一番努力,Miguel 、Héctor 跟 Miguel 陰間的親人聯合起來揭發了 Ernesto,並且順利送 Miguel 回去,讓故事有了一個快樂的結局。
  • Thor: Ragnarok (IMDB, Wikipedia),台譯:雷神索爾3-諸神黃昏。影評不錯,看完以後,我也覺得很歡樂,跟前面兩集的風格迥然不同。
    一開始是 Thor 在打火神,火神告訴他 Odin 已經不見了。於是 Thor 打完火神以後,回去阿斯嘉揭穿 Loki ,要 Loki 帶他一同去找父親。兩人到了地球遇到奇異博士,奇異博士在確認來意以後,開傳送門讓他們找到 Odin。三人聊了一陣子,Odin 說自己死期已到,要他們注意諸神黃昏。沒多久,Hela 就來了,Thor 跟 Loki 根本打不贏超強戰力的 Hela,於是 Thor 要求傳送回阿斯嘉,但 Thor 跟 Loki 在傳送中途就掉落了。Hela 回到阿斯嘉,展開報復,並找到跟班。
    Thor 發現自己掉到 Sakaar,並且淪為俘虜,必須跟其他俘虜戰鬥。在這裡他遇到了 Hulk ,曾經是女武神的 Valkyrie,以及 Loki,Thor 經過一番努力,說服了 Hulk, Valkrie 與 Loki ,三人合作加上其他俘虜幫忙,推翻了 Grandmaster,並且回到阿斯嘉去阻止 Hela。在阿斯嘉打鬥時,Thor 找到新的力量,而且認知到諸神的黃昏是不可避免的,於是他請 Heimdall 與在 Sakaar 認識的俘虜們將阿斯嘉的人都帶走,放出火神,讓火神跟 Hela 同歸於盡。
  • Knock knock (IMDB, Wikipedia),台譯:當辣妹來敲門。這部電影蠻警世的,主角 Evan 犯了天下男人都可能會犯的錯,導致失去幸福的家庭。
    建築師 Evan 有著幸福的家庭,在某個周末,他要趕進度,沒辦法跟妻兒去度假,所以妻子帶著孩子們去度假。當天晚上,外面下著大雨,Evan 進度趕的有點卡。就在此時,響起了電鈴聲,Evan 打開大門,是兩個楚楚可憐的辣妹來按門鈴求援。心裡有柔軟角落的 Evan 就讓他們進來洗澡,還幫她們烘乾衣服、叫車。想不到衣服烘乾後,兩個女孩還沒出來,就到浴室門口看看,兩個火辣的女孩突然冒了出來,挑逗 Evan,把持不住的 Evan 就這樣跟兩個女孩做了不應該做的事情。隔天早上起來,Evan 發現這兩個女孩不對勁,想把她們攆走,卻被她們要脅。僵持了好一陣子,火了的 Evan 將她們載到遠遠的地方去。
    回到家的 Evan 趕緊收拾家裡的殘局,豈料兩個女孩尾隨而至,將 Evan 綁了起來,開始玩弄 Evan。在玩弄的過程裡,兩個女孩還殺了來搬 Evan 妻子藝術品的經理人。最後,結局有點出乎我意料之外,因為並不是快樂結局,而是 Evan 被埋到地下,只剩下一顆頭在地上,女孩們將 Evan 不應該跟她們做的事情錄影上傳到 Evan 的 Facebook 塗鴉牆上,就拍拍屁股走了。而在這個時候,妻子跟孩子也回到家中,Evan 後悔莫及,電影在 Evan 悔恨的大叫中結束。
  • My big fat greek wedding (IMDB, Wikipedia),台譯:我的希臘婚禮。以前看到這片名,覺得這有什麼好看的,後來在網路上看到影評,才知道這片蠻有意思。電影的編劇同時也是女主角,電影裡所發生的故事有一部份就是她自己的親身經歷。
    30 歲在家族餐廳工作的 Toula 並不算漂亮,因為身處於希臘家庭,被希臘的傳統觀念給束縛住,爸爸老是叨念她應該趕緊找個人嫁了。直到她決心改變自己,並且透過媽媽的幫忙,她再次唸書。上學以後,心境的改變讓她變得自信而且漂亮。畢業以後,她到姨媽的旅行社上班。在旅行社上班的時候,之前在餐廳遇到的一位讓 Tuola 心動的男生居然反過來追她了,進而開始了一段浪漫有趣的愛情,最後兩人決定結婚。整個過程非常的有趣、溫馨,也讓我感受到,當你想改變的時候,是真的可以讓世界有所不同。
  • Jumanji: Welcome to the Jungle (IMDB, Wikipedia),台譯:野蠻遊戲-瘋狂叢林。預告看起來不錯,實際上也真的還不錯,基本上套路跟前作相似,蠻好的娛樂片。
    電影一開始交代了前作的棋盤遊戲變成了電子遊戲,並且讓一個孩子失蹤了。經過 20 年,四個被留校的孩子被派去地下室服務,他們找到了這個電子遊戲,然後就進去冒險了。四個孩子在遊戲裡都變身成特定的角色,與現實生活裡大不相同。經過一番冒險之後,四人找到了之前失蹤的孩子,也盡釋前嫌,一同努力打倒大魔王,重新回到現實世界,帶著在遊戲裡找到東西,繼續生活。

星期三, 4月 11, 2018

Django 節省記憶體的一些紀錄

前一陣子在改寫程式,避免使用過多記憶體時的一些紀錄。

pympler


pympler 很好用,主要是用來察看記憶體用量。缺點是得自己安插 code 觀看,之後再移掉。文件裡有不少用法,我只用到兩種。
第1種用法是 asizeof.asizeof(obj) ,這可以看物件使用的記憶體用量。

from pympler import asizeof
obj = {'foo': 'bar'}
print(asizeof.asizeof(obj))
第2種用法是 summary/muppy,這可以察看一段程序執行後的記憶體差異。

from pympler import summary, muppy
sum1 = summary.summarize(muppy.get_objects())
# do works
sum2 = summary.summarize(muppy.get_objects())
diff = summary.get_diff(sum1, sum2)
summary.print_(diff)
# 要輸出到 logging 的話,可以用 format_ 或 _format_table
# for line in summary.format_(diff):
#   logger.debug(line)
這段根據文件也可以使用 tracker.SummaryTracker() 來代替。
參考資料:

yield / generator

函式如果要傳回大量的資料,使用 yield ,這可以避免佔用大量記憶體,只有在 iterate 時,才一次一次拿回來。

def foo():
  for i in range(100000000):
    yield i  # 這讓 foo 的傳回結果變成 generator 物件

for x in foo():
  print(x)

Django Queryset

可以的話,儘量使用 values() 跟 values_list() 並指定所需的欄位,除了可以提升速度之外,也減少記憶體用量。
values() 是將記錄作為一個 dict 傳回,而 values_list() 則是將紀錄作為一個 tuple 傳回。這樣可以省去還原為 Django model object 的程序,因此速度會更快,記憶體使用的更少。而使用 values_list() 比 values() 來的更省,這是因為 tuple 所佔用的記憶體比 dict 來的少。

星期三, 3月 28, 2018

Using jinja2 as django template engine

Django 1.8 以後已經可以選擇使用自家的 template engine 或是使用 jina2 template engine 了,而且是可以混用,不限制你只能使用其中一種。
第一步是先安裝 jinja2:
pip install jinja2
第二步是在 settings 裡的 TEMPLATES 裡增加 jinja2 的設定:
TEMPLATES = [
    # 省略 django template 的設定
    {
        'NAME': 'jinja2',
        'BACKEND': 'django.template.backends.jinja2.Jinja2',
        'DIRS': [
            # insert more TEMPLATE_DIRS here
            # join(BASE_DIR, 'templates'), 
        ],
        'APP_DIRS': True,
        'OPTIONS': {
            'environment': 'your_project.jinja2.environment',
        },
    },
]

第三步,是在 your_project 下建立 jinja2.py ,內容:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import    # 使用 absolute_import 很重要!!!
import logging
from django.utils import translation
from django.contrib.staticfiles.storage import staticfiles_storage
from django.urls import reverse
import jinja2


logger = logging.getLogger(__name__)


def environment(**options):
    env = jinja2.Environment(
        extensions=['jinja2.ext.i18n', 'jinja2.ext.with_'],
        **options)
    env.globals.update({
        'static': staticfiles_storage.url,
        'url': reverse,
    })
    env.install_gettext_translations(translation)    # 使用 django 的 i18n/l10n
    return env
在這裡,我遇到一個奇怪的狀況,python 2 一直告訴我 jinja2 沒有 Environment,後來看了這篇,才知道是 absolute/relative import 問題,使用 absolute_import 以確保 import 的 jinja2 是正確的,而不是 django 的 jinja2。我想,python 3 應該不會有這問題。
django template 是使用 load 載入模組,jinja2 則需要在 Environment 初始化時就定義。
第四步,是在繼承 TemplateView 的類別裡,加入
template_engine = 'jinja2'
,然後在 your_app 下建立 jinja2 路徑,將 template 檔案放在那裡即可。

class Jinja2Test(TemplateView):
    template_name = 'jinja2test.html'  # template file 的名稱是 jinja2test.html ,檔案必須放在 your_app/jinja2 下。
    template_engine = 'jinja2'  # 表示要使用 jinja2 template engine,這個 jinja2 是定義在 settings 裡的 NAME

    def get_context_data(self, **kwargs):
        ctx = super(Jinja2Test, self).get_context_data(**kwargs)
        ctx['foo'] = 'bar'
        ctx['hello'] = 'world'
        return ctx
參考資料:

星期二, 3月 27, 2018

電影流水帳(2018/1/9~2018/2/20)

一下就過了一個月...
Gal GadotGal Gadot ,在蝙蝠俠大戰超人裡飾演神力女超人 (Wonder woman),在大戰時幫蝙蝠俠擋住致命一擊的一幕真的是太有戲劇性了。
  • Geostorm (IMDB, Wikipedia),台譯:氣象戰。譯名會讓人誤導故事的內容,原本以為是不當的利用科學而導致地球浩劫,實際上是純粹政治權謀的操作。
    哥哥帶領著世界的團隊開發了可以控制地球氣候的衛星系統,可是在完成的時候,被高層以弟弟換掉了。時間很快過了三年,哥哥並沒有因為時間而把這事情放下。就在這時,這個氣候系統讓地球的氣候發生了異常,都查不出所以然,只好派出當初的開發者哥哥上太空去調查。經過一連串的事情跟調查,哥哥發現可能是總統為了大位而作的,就請在地球的弟弟去作進一步的查證。弟弟在查證以後,發現其實是國務卿的陰謀,經過一番的打鬥,終於逮捕了國務卿,讓一切恢復正常。
    我覺得很有趣的一段是弟弟跟未婚妻探員保護總統逃走的過程,他們在車上閒聊的時候,總統知道這勇敢的探員是弟弟女友時,直喊你一定要娶她。我忘了詳細的對話,但這段真的蠻有趣的。
  • Logan (IMDB, Wikipedia),台譯:羅根。風格跟之前的金鋼狼故事完全不同,走出截然不同的故事,我滿喜歡的。
    羅根年紀大了,帶著同樣也老了的 X 教授跟 Caliban 一起生活,他靠著開車載客來賺取生活費用。有一天,有個人來叫車,羅根到了那兒,發現是個女人要他送個女孩-蘿拉去邊境,羅根不肯。但後來那女人死了,羅根只得帶著蘿拉回去,跟 X 教授商量怎麼作。X 教授發現蘿拉是個變種人,羅根不太相信,可是過了沒多久,就有某個生物科技公司前來索討蘿拉。羅根不肯,帶著 X 教授逃走,生物科技公司因為 Caliban 有追蹤的能力,就強逼他去追蹤羅根、X 教授跟蘿拉。在逃亡的途中,慢慢帶出羅根為什麼帶著 X 教授的事情以及蘿拉的經歷。蘿拉是生物科技公司利用羅根的基因所複製、改造出來的,逃出公司的還有其他孩子,同樣也是以變種人的基因改造出來的。
    後來三人在路上遇到農夫,被農夫一家邀請吃晚餐,並借宿一晚。X 教授睡了很好的一覺後,以為羅根回來了,就帶著懺悔的心情娓娓道出他其實明白自己害死了其他 X 戰警的事情,可是這個羅根是複製品,就這樣被複製的羅根給殺死。羅根之後帶著哀慟送蘿拉到了邊境,見到這些孩子,孩子們打算隔天就越境到加拿大去。羅根不打算跟著他們,跟蘿拉告別,但在護送蘿拉到這裡的過程裡,他心裡原本悲觀的想法有點改變了。隔天,孩子們早早就啟程離開,但羅根發現生物科技公司緊追不捨,已經展開大規模的追捕。他趕過去,透過藥物的幫忙,幫助孩子們對抗生物科技公司的追捕,經過一番大戰以後,成功的阻止生物科技公司,讓孩子們順利的越境,可是自己的生命也走到了終點。
  • Ghost in the shell (IMDB, Wikipedia),台譯:攻殼機動隊。之前有看過一部份動畫,這陣子剛好 HBO 有上映,就看了。
    素子是個改造人,由阪華機械進行改造,她忘了過去的事情,只記得現在在公安九課協助追捕罪犯。在追捕一個犯人的過程中,她慢慢找回了自己的過去,知道了阪華機械公司的醜陋事情。在公安九課以及改造她的科學家的幫助下,打倒了阪華機械,大概就這樣。
    基本上我覺得故事本身而言不算改動太大,選角也能接受,比較讓我不能接受的是可愛的 Tachikoma 攻殼車變得太不可愛了。
  • Fantastic Beasts and Where to Find Them (IMDB, Wikipedia),台譯:怪獸與他們的產地。延續哈利波特的風格,沒看過原著,但表現中規中矩,不難看。不過我覺得女主角的妹妹還蠻搶戲的,滿喜歡她。
    Newt 來到美國要讓一個奇獸回到原生地,結果卻捲入連續的殺人事件裡,甚至還被冤枉。但最後水落石出,找出真正的凶手,並且解決事件。
  • The boss baby (IMDB, Wikipedia),台譯:寶貝老闆。故事的設定相當有趣,嬰兒是統一由寶貝公司派去想要孩子的家庭,但是公司上層發現嬰兒的需求數愈來愈低。在調查之後,發現市場是被狗狗公司所侵佔,於是為了奪回市佔,寶貝公司派出特務到狗狗公司員工的家庭裡進行調查。狗狗公司員工的家庭裡有個小男孩,但這個小男孩發現了特務是個成熟的嬰兒的事情,在事情曝光之下,這個嬰兒跟這個小男孩在不打不相識之後,為了相同的目的,決定攜手合作。在調查之後,他們發現狗狗公司即將發表一個新產品,於是他們打算在狗狗公司新產品發表會時,將新產品搶走。孰料卻中了狗狗公司總裁的計謀,狗狗公司的總裁原來是寶貝公司的厲害人物,但卻被裁掉,變成了大人,他懷恨在心,就處心積慮的研發新產品打擊寶貝公司。這次的新產品就是藉助寶貝特務的奶瓶,來讓狗狗不會長大。眼看任務就要失敗,兩人相互打氣,展開行動,聯手阻止產品發表會,順利解決。最後,寶貝特務還是到了小男孩的家庭裡,當了他的弟弟。
  • Batman v Superman: Dawn of Justice (IMDB, Wikipedia),台譯:蝙蝠俠大戰超人-正義曙光。因為超人鋼鐵英雄故事裡的大戰,布魯斯·韋恩(就超人啦~)不太開心,積極的找對付超人的方法。在這段期間,雷克斯·路瑟也推波助瀾地讓他們相互誤解。到了最後,雷克斯·路瑟在無法讓超人跟蝙蝠俠相互內鬨的情況下,利用氪星的科技,復活了薩德將軍,讓薩德將軍去打擊蝙蝠俠跟超人,在大戰之中,之前布魯斯·韋恩意外發現的女超人也加入混戰。混戰的最後,超人拿了蝙蝠俠所打造的氪星長矛殺死了變種的薩德將軍,自己也壯烈犧牲。在超人的葬禮上,女超人問了蝙蝠俠哲學的問題,蝙蝠俠感佩超人的人格,表示會再去找其他的英雄一起來保衛世界,埋下正義聯盟的伏筆。
  • 奇門遁甲 (IMDB, Wikipedia)。似乎是要向以前的「奇門遁甲」致敬,我是忘了之前的故事是什麼,不過故事看起來並沒有相關。電影的特效是還不錯,不過故事就乏善可陳,電影的結尾看起來是還有續集,唉~
    故事圍繞在霧隱門上,霧隱門是個神祕的門派,以特殊的武功與技藝保護著一個被封印起來的妖怪,並秘密尋找未來的掌門人與御神機。在因緣巧合之下,一個捕快介入了,被封印的妖怪被另外一個妖怪救了出來,天下開始大亂。霧隱門的二師兄在此時找到未來的掌門人小圓,回來霧隱門跟眾人展開行動。而老大則找到了御神機,跟武林其他門派一同搶奪,妖怪在此現身,說明了他的陰謀,拿回御神機的同時,也將加入爭奪的門派掌門人收為己用。在過程裡,霧隱門人發現了小圓有著神奇的能力,並且與妖怪展開鬥爭,最後在小圓的威能協助之下,打敗了妖怪。但事情還沒了結,還有故事沒交代完。

您或許對這些文章有興趣

Related Posts Plugin for WordPress, Blogger...