2014年5月15日木曜日

kickstarterのプロジェクトを紹介するブログをはじめてみる

http://kickstarter-navi.blogspot.jp/

クラウドファンディングサイト、kickstarterのプロジェクトを紹介するブログを始めました。Web業界に身を置く以上、常に最先端のテクノロジには触れておきたい、という大義名分はさておき、昔ながらのガジェオタ基質を奮い立たせるために、kickstarterのプロジェクトを紹介していくブログを初めてみました。

日本でもCAMPFIREなどのクラウドファンディングサイトが登場し始めていますが、まだまだシリコンバレーを中心に広がるクラウドファンディングの波には乗りきれていないと思います。もちろん英語も壁になっているでしょうが、それだけでなく、形がある商品のような場合余計に送料がかかるなど、kickstarterで出資するハードルは高いと思われます。ですので、そのあたりの不安を払拭するためのレポートなんかも掲載していけたらな、と、もやっとながら考えております。

とりあえずここと同じくてっとり早くbloggerで始めましたが、プロジェクト同士のつながりや、最新の出資額の表示ウィジェットを作ったりいろいろやってみたいので、そのうちWordpressなりに移行予定。

2014年5月13日火曜日

Windows7にsetuptoolsをインストールする際のエラー

Windows7にPython2.7をインストールした後、pipを使うためにまずsetuptools(easy_installコマンド)をインストールしようと思い、公式からez_setup.pyをとってきて実行、一瞬コマンドプロンプトが立ち上がって、無事インストール完了。と思いきや、easy_installが使えない。パスが通ってないかな?と思って確認するも、問題なし。。

ううむ、もう一度ez_setup.pyを実行してみると、一瞬、赤い文字が・・・。いやーな予感。。コマンドプロンプトからコマンドでez_setup.pyを実行してみたところ、以下のようなエラーがでていることを確認しました。

長らく使っているPythonを入れてこんな序盤で躓くとは思ってもいませんでした。


Python2.xにありがちなUnicodeのエラーが。でもなんでこんなところで出ているんでしょう?よく見ると、registryの文字が。どうやらレジストリ周りにUnicodeが含まれている疑いが。レジストリエディタを見てみたところ、以下のような怪しい文字列を発見。 


変な中華ソフトをインストールした記憶はないし、レジストリのキーにマルチバイト文字を入れるなんてけしからん、と思ってたのですが。いろいろ調べてみると、VLCが犯人であることが判明。UTF-16によるエンコーディングバグなのだとか。こういうバグを踏むことが多くてついてない今日このごろ。

とはいえレジストリのこんな特殊なキーを拾ってきてデコードエラーを吐くPythonもPythonだよなー、と思いつつも、なかなかPython3.x系に乗り換えられないのでした。

Versions

  • Windows 7 64bit
  • Python 2.7.6 x86-64
  • setuptools 3.6




2014年5月11日日曜日

pythonでファイルアップロードの進捗をリアルタイム取得する

pythonでサーバに対しurllib2やrequestsなどのモジュールでファイルをアップロードする場合、基本的に
urllib2.urlopen(request)

requests.post()
の形式で投げることになりますが、f.read()のような形で、引数としてファイル全体を与えてしまった場合、アップロードが完了するまで待たなければなりません。そのため、大きなファイルのアップロードなどでは特に、本当にアップロードが進んでいるのか知ることができず不便でした。

そこで、StringIOを使ってファイルをchunkに分割してロードできるようにし、read()が走るたびにコールバックを呼ぶようにしてやることで、アップロード中の進捗状況を知ることができるようになります。こちらを参考にしてStringIOを継承してコールバック関数を呼ぶためには、以下のように書けます。
from StringIO import StringIO
class BufferReader(StringIO):
    def __init__(self, buf='',
                 callback=None,
                 cb_args=(), cb_kwargs={}):
        self._callback = callback
        self._cli_manager = cli_manager
        self._progress = 0
        self._cb_args = cb_args
        self._cb_kwargs = cb_kwargs
        StringIO.__init__(self, buf)

    def __len__(self):
        return self.len

    def read(self, n=-1):
        chunk = StringIO.read(self, n)
        self._progress += int(len(chunk))
        self._cb_kwargs.update({'progress': self._progress})
        if self._callback:
            try:
                self._callback(*self._cb_args, **self._cb_kwargs)
            except Exception, e: # catches exception from the callback
                raise BaseException, e

これで、
req = urllib2.Request(url, BufferReader(f.read(), callback=callback_func))
res = urllib2.urlopen(req)
とすることでcallback_funcにファイルアップロードの進捗を渡すことが可能になります。

ただし、multipartによるPOSTでファイルをアップロードする場合には、requests.post(files={'file': (filename, BufferReader(filebuffer))})の形式ではStringIOを使っても上記のread()が正しくchunkごとに呼ばれないようです。この場合はurllib3のencode_multipart_formdata()を使ってあらかじめmultipart用のデータを作り、この結果をBufferReaderに噛ませたあとrequests.post(files=)に入れてやることでアップロードするなどの方法をとる必要があります。