æè¿æµè¡ã£ã¦ããé°å²æ°ãããPythonã ãã©ã僕も年末にふと気分が高まったã®ã§ãç·´ç¿ããã¦ã¿ãã
èªåã«ã¨ã£ã¦ã¯PerlãRubyãããå ã«åå¼·ãããåãã¦ã®ã¹ã¯ãªããè¨èªãPythonã ã£ãã®ã§ãã¡ãã£ã¨ã ãæãå ¥ãããããã¨ã¯ãããä½å¹´ãåã«åãã¦ã®Pythonã§åå¼·ããå¾ã¯ã稀に使うくらいだったã®ã§Pythonãªãã§ã¯ã®è¯ãæ¸ãæ¹ã¨ããè¯ãã©ã¤ãã©ãªã®ç¥è¦ã¨ãã¯å ¨ç¶æã£ã¦ãªãã£ãã
ããã§ãPythonã«å ¥éããªããã¦Pythonæµãæãåºããå¾ãèªåãæ°ã«ãªã£ã¦ããWebéçºããã£ã¦ã¿ã¦ã©ããããããªã®ããä¸éããã£ã¦ã¿ãã
ãã®ã¨ã³ããªã¯ãGoでWebアプリケーション作る練習をしたã®ç¶ç·¨ã§ã(ããã«ç¶ãã¯ãªãã§ããã)ã
å ¥é Python3 ãèªãã

- ä½è : Bill Lubanovic,æè¤åº·æ¯ ,é·å°¾é«å¼
- åºç社/ã¡ã¼ã«ã¼: ãªã©ã¤ãªã¼ã¸ã£ãã³
- çºå£²æ¥: 2015/12/01
- ã¡ãã£ã¢: åè¡æ¬ï¼ã½ããã«ãã¼ï¼
- ãã®ååãå«ãããã° (2件) ãè¦ã
ä¸éãã®ææ³ãæãåºããã¨ãããã¨ã§ã¨ããããèªãã§ã¿ããä»ã®è¨èªãä¸éããã£ã¦ããã°æ°ããæ¦å¿µã¯ã»ã¨ãã©ãªãã®ã§ãµã¯ãµã¯èªãããåã¯3,4æ¥ãããã§ã ãããç®ãéããã
ãã£ã¨èªãã ãã¨ã§ãPythonãªãã§ã¯ã®ãªã¹ãå å 表è¨ã¨ããé¢æ°ãã³ã¬ã¼ã¿ã®è©±é¡ã¨ããæãåºãããã¨ãåºæ¥ã¦ããã£ããPythonã£ã¦ãªãã©ã«ã«Setåããããã ãªã¼ã¨ãã
Pythonã®ææ³ã®è©±é¡ã ãã«ã¨ã©ã¾ããããã¹ãããã¼ã¿ãã¼ã¹ã¸ã®ã¢ã¯ã»ã¹ãHTTPã¯ã©ã¤ã¢ã³ãããµã¼ã(WSGI)ã®è©±é¡ã«ã¤ãã¦ä¸éãæãã¦ãããã®ãè¯ããæè¿ã®æ¬ããããNoSQL(Redis)ãã¡ãã»ã¼ã¸ã³ã°ãã¥ã¼(ZeroMQ)ãããã®è©±é¡ãåãä¸ãããã¦ãããåç« ã«ç·´ç¿åé¡ãã¤ãã¦ãã®ã§å®éã«æãåãããã¨ãã§ããã
ã¯ã¦ãªã¤ã³ã¿ã¼ã³ã®äºå課é¡
ã¯ã¦ãªã¤ã³ã¿ã¼ã³åå è ã¯ãã¯ã¦ãªãªãã£ã¹ã«ãã£ã¦ããã¾ã§ã®äºç¿ã¨ãã¦ãäºå課é¡ã¨ããã®ããããã¨ã«ãªã£ã¦ãããちょっと古いけど公開されていてãPerlçã¨Scalaçãããããã®èª²é¡ãPythonã§è§£ãããã½ã¼ã¹ã³ã¼ãã® python-Intern-Exercise はこちらã
ãã®äºå課é¡ã¯ãããã°ã©ã ã®åºæ¬çãªæ¸ãæ¹ããã¡ã¤ã«I/Oããã¹ããªã©ã網ç¾
ãã¦ããã®ã§ãåãå
容ã®èª²é¡ãPerlãScala以å¤ã®è¨èªã§ããã¨è¯ãç·´ç¿ã«ãªã£ã¦ãããããã¡ãã£ã¨åã« id:shiba_yu36 ããããã£ã¦ããã Java版はこちらã
Webã¢ããªã±ã¼ã·ã§ã³ã®å®è£
ããã«ç·´ç¿ã¨ãã¦ãPythonã§Webã¢ããªã±ã¼ã·ã§ã³ãä½ã£ã¦ã¿ããã¨ã«ããããããã調ã¹ãªãããèªåãããããã¹ã¿ã¤ã«ã§Webã¢ããªã±ã¼ã·ã§ã³ãæ¸ãã¨ã©ãããæãã«ãªããã調ã¹ã¦ã¿ãã
çµè«ã¨ãã¦ã¯ãPythonã§ã©ãããæ¸ãæ¹ãããã¨è¯ãã®ãã¨ããã©ã®ã©ã¤ãã©ãªã使ãã®ãã¨ãã£ããã¨ã調ã¹ãã®ã«ã¯æéãããã£ããã®ã®ããããããããã°ãã ããããããããã¨ã¯ã§ããã¨ãããã¨ãããã£ãã
æ®æ®µã¯Perlã使ã£ã¦ããã®ã ãã©ãPerlã§ä½¿ã£ã¦ãããã¯ããã¯ãã©ã¤ãã©ãªã¯ã ããã対å¿ãããã®ããã£ã¦åãããæ¹ãéç¨ããæããä¾ãã°ãテストの感じã¨ãã¯ããã¤ãæ¸ãã¦ããPerlã®ã³ã¼ãã«è¿ãã¤ã³ã¿ã¼ãã§ã¼ã¹ã®ãµãã¼ãé¢æ°ãå©ç¨ã§ããããã«ã§ããã
ãããããã¨ä½ãã®åèã«ãªããããããªãã®ã§ãå®è£ ã®æ¹éãç´¹ä»ãã¦ããã¦ã¿ãã
Perlã§Webã¢ããªã±ã¼ã·ã§ã³ãä½ãã¨ãã«ããããã£ã¦ãããèããã¬ã¼ã ã¯ã¼ã¯ã®ä¸ã«ãªãã¹ãã·ã³ãã«ã«ã¢ããªã±ã¼ã·ã§ã³ãæ§ç¯ããã¨ããæ¹éã§ã¤ãã£ã¦ãããè¤éãªããã¿ã¯ä½¿ããè¦éãã®è¯ããéè¦ãã¦ãã使ã£ã¦ããã©ã¤ãã©ãªã¯æä½éã§ä»¥ä¸ã®æ§ãªæãã
- Webãã¬ã¼ã ã¯ã¼ã¯: Flask
- ãã¼ã¿ãã¼ã¹: ORMã¯ä½¿ããã« mysqlclient ããã®ã¾ã¾å©ç¨
- ãã¹ã: nose (追è¨: èè ã«ããã¨ä»éçºæ¢ã¾ã£ã¦ãã®ã§ããã¾ã使ããªãã»ãããããããã£ãï¼)
ãã¡ã¤ã«ããªã¼ã¯ä»¥ä¸ã®ãããªæãã«ãªã£ã¦ãã¦ãããããã®å½¹å²ãæ¸ããã
. âââ db/ â  âââ schema.sql âââ hakoblog/ â  âââ config.py # ã¢ããªã±ã¼ã·ã§ã³è¨å®ç¨ã®ã¯ã©ã¹å®ç¾© â  âââ model/ # ã¢ããªã±ã¼ã·ã§ã³ã®ã¢ãã«å®ç¾©(BlogãEntryãªã©) â  âââ loader/ # ã¢ãã«ãªãã¸ã§ã¯ãããã¼ã¿ãã¼ã¹ããåå¾ããã¯ã©ã¹ãå ¥ã£ã¦ã â  âââ action/ # ã¢ããªã±ã¼ã·ã§ã³ã«å¯¾ãã¦ç ´å£çãªæä½ãè¡ãã¯ã©ã¹ãå ¥ã£ã¦ã â  âââ db.py # ãã¼ã¿ãã¼ã¹æ¥ç¶ãæ½è±¡åããã¯ã©ã¹ã®å®ç¾© â  âââ web.py # Webã¢ããªã±ã¼ã·ã§ã³ã®ã«ã¼ãã£ã³ã°ã¨ã³ã³ããã¼ã© â  âââ templates/ # HTMLãã³ãã¬ã¼ã âââ tests
ORMã¯ä½¿ããªãã®ã§ãmodel
ã®å®ç¾©ã¯åç´ãªPythonã®ã¯ã©ã¹ã«ãªã£ã¦ãã(ä¾: Entryクラス)ã
ã¢ãã«ãªãã¸ã§ã¯ãããã¼ã¿ãã¼ã¹ããåå¾ããã«ã¯loader
å
ã§å®ç¾©ãããã¯ã©ã¹ã使ããã¯ã©ã¹ã¯ãã ã®ãã¼ã ã¹ãã¼ã¹ã§ãã¯ã©ã¹ã¡ã½ããã¨ãã¦å¦çãå®ç¾©ãããä¾ãã°ãUserLoader
ã¯ä»¥ä¸ã®ãããªé°å²æ°ã«ãªãã
from hakoblog.model.user import User class UserLoader(): @classmethod def find_by_name(cls, db, name): with db.cursor() as cursor: cursor.execute( ''' SELECT id, name FROM user WHERE name = %s LIMIT 1 ''', (name, ) ) row = cursor.fetchone() if row is None: return None return User(**row)
SQLå ã«%sãåºã¦æ¥ãã®ã§ãããã¨ãããã©ãããã§ã¡ããã¨placeholderã«ãªã£ã¦ãã(mysqlclientã®ä»æ§ã§%sã使ã)ã
ç ´å£çãªæä½ãããã¨ãã¯action
ã«åæ§ã®ã¯ã©ã¹ãå®ç¾©ãããã¨ã«ããã£ãã責任ãããã¦ããããããããã¨ã§ãã¼ã¿ãèªã¿è¾¼ã¿ã¤ã¤ç ´å£çãªæä½ãå®ç¾©ãã«ãããªãçãããã£ããããã
db.py
ã¯DBã¯ã©ã¹ãå®ç¾©ãã¦ãã£ã¦mysqlclient
ã©ã¤ãã©ãªãèãã©ãããã¦ãããæ¥ç¶ã®ããã®è¨å®ãèªã¿è¾¼ãã ããã¡ãã£ã¨ããã¦ã¼ãã£ãªãã£é¢æ°(ä¾: uuid_short関数)ãå®ç¾©ããã®ã«ä¾¿å©ã
web.py
ã§ã¯ãHTTPã®ã«ã¼ãã£ã³ã°ã¨ã³ã³ããã¼ã©ãå®ç¾©ãã¦ãããã¢ããªã±ã¼ã·ã§ã³ã®ã¨ã³ããªãã¤ã³ãã¯ããã«ãªãã
å®è£ ã試ãã®ã主ç®çãªã®ã§å®ç¨æ§ã¯ã¾ã£ãããªããè¨äºæ¸ãããè¨äºãèªãã ãã¯ã§ãããã©ãã¦ã¼ã¶èªè¨¼ãªã©ã¯ãªãããã¹ã¿ã¤ã«ãæ¸ãã¦ãªãã¦ã¿ããã¯éçã«è¿ãããã¼ãã
ææ³
ã¡ãã£ã¨Pythonã«å ¥éãããã¨ããããã調ã¹ãªããPythonã§Webã¢ããªã0ããæ¸ãã¦ã¿ãã
å½ç¶ãæ®éã«Webã¢ããªã±ã¼ã·ã§ã³ã¯æ¸ããããã ãã©ãPerlã§ãã¤ããã使ãè¨è¨ã¹ã¿ã¤ã«ãç¡çãªãæ¡ç¨ãããã¨ãã§ãããã¨ãããã£ãã®ã¯è¯ãã£ããã³ã¼ããæ¸ãã¦ã¿ãã¨ãæ¨èª*1ã®ã¨ããã§ãä¸ã¤ã®ãã¨ãããããæ¹ãã ããã決ã¾ã£ã¦ããã®ã§ãè¿·ããã«ã©ãã©ãæ¸ãé²ããããã®ã¯å¿å°ããã£ãã
ããã¾ãåã£ããã¨ãããªãæåã£ã½ããã©ãå¿ è¦ã«ãªã£ãããã£ã¦ããã¨ããæããããã®ããªãã¨ãªãããã£ã¦ãããä¾ãã°ããã¹ãã®ããã«æéãã¨ããã©ã¤ãã©ãª(freezegun)ã¨ãã¯ã¡ããã¨ãã£ãããã¦ãæè»æ§ã大äºã«ããã¦ãããã
ã¹ã¯ãªããè¨èªã¨ãã¦ãªããªãè¯ããã©ã³ã¹ã ããWebéçºããã¾ãã§ããããªãã¨ãä½é¨ã§ãããããã§ãªãã¦ããæ©æ¢°å¦ç¿ããã¼ã¿ãµã¤ã¨ã³ã¹åéã§å¢ãã®ããè¨èªã ã¨æãã®ã§ãããã¡ãã£ã¨ç·´ç¿ãã¦ä½¿ããããã«ãã¦ããã¦ãè¯ãããã
*1:There should be one-- and preferably only one --obvious way to do it.