ラベル python の投稿を表示しています。 すべての投稿を表示
ラベル python の投稿を表示しています。 すべての投稿を表示

2015年3月1日日曜日

Django + Polymer : Ajax 時の CRFS 対策 (403 エラーへの対応)


このエントリーをはてなブックマークに追加
ここ に書いたように url に View を登録するときに csrf_exempt を使うことで CSRF 対策を切って 403 エラーを回避していましたが、Polymer 使用時には Django-enabled Polymer core-ajax variant を使うことで簡単に対応できる事がわかりました。
  1. リンク先の django-ajax を django-ajax.html という名前で保存する
  2. Polymer 内で core-ajax を使っていた部分を django-ajax に置き換える
    1. インポートを忘れずに
  3. {% csrf_token %} を html に含めてレンダリングする
django-ajax は core-ajax を継承していて、ajax 時のヘッダに csrf トークンを追加してくれる、という寸法のようです。

先人の知恵というのはありがたいものですね。リンク先に感謝です。

2015年2月20日金曜日

Django : Ajax POST 時に 403 エラー出る場合の対処法


このエントリーをはてなブックマークに追加
幾つか解決策はあるようですが、ひとまず url 登録時に csrf_exempt をつけています。
おそらくセキュリティ的にあまりよくなさそうなので Cross Site Request Forgery protection 辺りを参照していずれきちんと理解したいと思います。。。

from django.views.decorators.csrf import csrf_exempt
....
url(r'^category$', csrf_exempt(MyViewClass.as_view())),

2015年2月19日木曜日

Google App Engine : ndb のデータを JSON 化する + json.dumps を date 対応させる


このエントリーをはてなブックマークに追加
MyModel.query().fetch() などで ndb.Model を取得した後、ndb.Model の to_dict() 関数を使用して json 化します。

to_dict() には key が含まれないので、key が必要な場合には明示的に追加します。


fetched_list = MyModel.query().fetch()
json_without_keyid = json.dumps([c.to_dict() for c in fetched_list ])
json_with_keyid = json.dumps([dict(c.to_dict(), **dict(id=c.key.id())) for c in fetched_list ])


追記

数字や文字列のみの場合上記のコードで問題なかったのですが、
DateProperty を使用していた Model は

File "C:\Python27\lib\json\encoder.py", line 184, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: datetime.date(2015, 2, 20) is not JSON serializable

というエラーで json 化に失敗してしまいました。
そこで、以下のように、date オブジェクトの場合の処理を追加した JSONEncoder を作成し、対応を加えました。datetime の場合なども同じような方法で対応できるはずです。


from datetime import date

class JSONDateEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, date):
            return obj.isoformat()
        return json.JSONEncoder.default(self, obj)


fetched_list = MyModel.query().fetch()
json_without_keyid = json.dumps([c.to_dict() for c in fetched_list ], cls=JSONDateEncoder)
json_with_keyid = json.dumps([dict(c.to_dict(), **dict(id=c.key.id())) for c in fetched_list ], cls=JSONDateEncoder)


参考:AppEngine Making ndb models json serializableHow to overcome “datetime.datetime not JSON serializable” in python?

2014年12月28日日曜日

Sublime Text : Python 実行時の [Decode error - output not utf-8]


このエントリーをはてなブックマークに追加
以下のページが参考になりました。
Windows の SublimeText3 で整える Python3 開発環境設定 (2014/02/23現在)

使っているものが Python 2系でも、指定するパスを変えるだけで原則は同じです。

Preferences -> Browse Packages... 開くフォルダに Python というフォルダを作り、そのフォルダ以下に Python.sublime-build というファイル名で以下の内容を保存します。
(参考先と比較して、shell_cmd の $file を " で括っている点と、python の path が 2.7系である点が異なります。)

{
    "shell_cmd": "python -u \"$file\"",
    "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
    "selector": "source.python",
 
    "windows":
    {
        "encoding": "cp932",   // Windowsコンソールの文字コード指定
        "path": "C:/Python27"  // 自分のPythonへのパスを追記
    }
}

Sublime Text 3 であれば
C:\Users\(ユーザ名)\AppData\Roaming\Sublime Text 3\Packages\Python\Python.sublime-build
のような場所に保存しておけば良いです。

これで Sublime Text 上から Ctrl + B で Python 実行が行えるようになりました。

もう少し詳しく Build について調べる場合は
非公式ドキュメントの Build Systems のページが参考になりそうです。

2013年8月3日土曜日

Python + Google App Engine で Twitter から呟く


このエントリーをはてなブックマークに追加
リマインダーや Tips を呟く自分専用の BOT を作ろうと思ってやってみました。
python-twitter を使います。
ライブラリの設定などで躓いたところをメモしておきます。

ライブラリの設定


python-twitter は simplejson, oath2, httplib2 が必要なので、これらのライブラリを Google App Engine(GAE) 上のプロジェクトで実行できるようにします。ライブラリのコードをプロジェクトに入れることで解決しました。

  • プロジェクトのルートディレクトリに python-twitter ライブラリの build/lib から持ってきた tiwtter.py を置きます。
  • oath2 ライブラリの build/lib 以下にある oath2 ディレクトリをルートディレクトリに置きます。
  • httplib2 ライブラリの build/lib 以下にある httplib2 ディレクトリを oath2 ディレクトリの下に置きます。
  • simplejson ライブラリの build/lib 以下にある simplejson ディレクトリをルートディレクトリに置きます。

最終的なディレクトリ構成は以下のとおりになりました。
│  app.yaml
│  cron.yaml
│  favicon.ico
│  index.yaml
│  main.py
│  twitter.py
│
├─oauth2
│  │  _version.py
│  │  _version.pyc
│  │  __init__.py
│  │  __init__.pyc
│  │
│  ├─clients
│  │      imap.py
│  │      smtp.py
│  │      __init__.py
│  │
│  └─httplib2
│          cacerts.txt
│          iri2uri.py
│          iri2uri.pyc
│          socks.py
│          socks.pyc
│          __init__.py
│          __init__.pyc
│
└─simplejson
    │  compat.py
    │  decoder.py
    │  encoder.py
    │  ordered_dict.py
    │  scanner.py
    │  tool.py
    │  _speedups.c
    │  __init__.py

python は __init__.py があるフォルダをライブラリのフォルダとして認識するので、これで twitter.api からは oath2 と simplejson が見えるようになり、oath2 からは httplib2 が見える…という寸法です。

twitter.Api のキャッシュの無効化


Google App EngineでTwitter(OAuth対応)を使うためのメモ

参考サイトから引用すると
Google App Engineでは、スタティックなファイルを作成等はできない。python-twitterはキャッシュとして、ファイルを作るために、そのままでは動作しない。APIオブジェクトを作成する際にcache=Noneをキーワードとしてつけておくこと。
です。なので、twitter.Api オブジェクトを作成するときは
api = twitter.Api(consumerKey, consumerSecret, accessToken, accessSecret, cache=None)
のようにして cache を無効化してオブジェクトを作成します。

アカウントの登録


BOT 用のアカウントを登録します。
PythonでTwitter BOTを作る を参考にしました。

ソースコード


GAE の URL にアクセスしたときに呟きます。これを cron の JOB に登録すれば、一定時間毎に呟く事が可能になります。
cron.yaml は以下の様な感じ。頻度は適当に。
cron:
- description: job
  url: /
  schedule: every 2 hours
あとは呟く内容を変える仕組みを作れば、自分専用の BOT としては形になりそうです。

2012年12月24日月曜日

JavaScript + Python + Flask - Origin null is not allowed by Access-Control-Allow-Origin


このエントリーをはてなブックマークに追加
ローカルで、 Python + Flask で立てたサーバーに JavaScript からアクセスしようとしたら

XMLHttpRequest cannot load http://localhost:5000/. Origin file:// is not allowed by Access-Control-Allow-Origin.
http://flask.pocoo.org/snippets/56/Decorator for the HTTP Access Control

というメッセージで読み込めなかった。

chrome.exe の起動オプションに --allow-file-access-from-files を付ければ良いらしいのだけれど、これでも上手くいかなかったので、python + Flask のサーバ側で何とかする事に。

Decorator for the HTTP Access Control の @crossdomain 修飾子を使う事で、問題回避。

@crossdomain(origin='http://localhost:50423') # Javascript をローカルサーバ実行時
@crossdomain(origin='*') # Javascipt を含む html をブラウザで読み込み時

こういう環境設定に時間を取られるのは何とかならないものか。

2012年11月4日日曜日

python - range で逆順


このエントリーをはてなブックマークに追加
参考 : range()で生成したリストの逆順を得る

range の第 3 引数が生成する配列の数値の間隔。
先頭と終端に注意。
# 0, 1, 2, 3, 4, 5, ..., 498, 499
range (0, 500)
# 499, 498, 497, ..., 3, 2, 1, 0
range (499, -1, -1)

2012年10月26日金曜日

python - etree を使った xml 解析


このエントリーをはてなブックマークに追加
SAX よりも直感的

from xml.etree.ElementTree import parse
# 読み込み
mapping = {}
tree = parse('books.xml')
for B in tree.findall('book'):
    isbn = B.attrib['isbn']
    for T in B.findall('title'):
        mapping[isbn] = T.text
        
pprint.pprint(mapping)

# 書き込み。文字コードを指定し xml_declaration=True にすると、
# 先頭に宣言() が入る
tree.write('out.xml', encoding="utf-8", xml_declaration=True)

2012年10月25日木曜日

python - SAX を使った xml のパース


このエントリーをはてなブックマークに追加
パースされている最中に呼ばれる関数を実装する。
自前で状態を保存しなければならないので、入れ子が多いなど複雑なファイルのパースには向きそうにない。

import xml.sax, xml.sax.handler, pprint

class BookHandler(xml.sax.handler.ContentHandler):
    
    def __init__(self):
        self.inTitle = False
        self.mapping = {}
    
    def startElement(self, name, attributes):
        if name == 'book':
            self.buffer = ""
            self.isbn = attributes["isbn"]
        elif name == "title":
            self.inTitle = True
    
    def characters(self, data):
        if self.inTitle:
            self.buffer += data
    
    def endElement(self, name):
        if name == "title":
            self.inTitle = False
            self.mapping[self.isbn] = self.buffer

parser = xml.sax.make_parser()
handler = BookHandler()
parser.setContentHandler(handler)
parser.parse('books.xml')
pprint.pprint(handler.mapping)
print handler.mapping

2012年10月20日土曜日

python - sqlite3 : テーブル一覧の取得


このエントリーをはてなブックマークに追加
sqlite_master から type="table" を select する
import sqlite3

conn = sqlite3.connect('sq.db')
cursor = conn.cursor()
cursor.execute('select * from sqlite_master WHERE type="table"')
for item in cursor.fetchall():
    print item

python - sqlite3 を使う


このエントリーをはてなブックマークに追加
connect  して cursor を作成してコマンドを実行する。
import sqlite3

conn = sqlite3.connect('sq.db')
cursor = conn.cursor()

cursor.execute('drop table people')

create_table_command = 'create table people (name char(30), age int(4))'

cursor.execute(create_table_command)

cursor.execute('insert into people values (?, ?)', ('Aoki',50))
cursor.executemany('insert into people values (?, ?)', [('Ishikawa', 70), ('Ueno', 40)])

conn.commit()

cursor.execute('select * from people')
print cursor.fetchall()

cursor.execute('select * from people where age >= 50')
print cursor.fetchall()

cursor.execute('update people set age=? where name = ?', (51, 'Aoki'))
cursor.execute('select * from people where age >= 50')
print cursor.fetchall()

python - shelve を使ったデータ保存


このエントリーをはてなブックマークに追加
キー、バリュー形式で簡単にデータの保存ができる。

import shelve

dbase = shelve.open('database')
dbase['1'] = ['a', 'b', 'c']
dbase['2'] = 2

for key in dbase:
    print dbase[key]
  
# shelv.open で writeback=True を指定しないと
# これでは dbase['1'] の中身は変更されない。  
dbase['1'].append('d')
dbase['2'] = 'Two'

for key in dbase:
    print dbase[key]

# dbase['1'] の中身を変更する。
tmp = dbase['1']
tmp.append('d')
dbase['1'] = tmp

for key in dbase:
    print dbase[key]

# データの削除
del dbase['1']
    
dbase.close()

2012年10月16日火曜日

python - socketserver の利用


このエントリーをはてなブックマークに追加
socketserver ( 2.x 系では SocketServer ) を利用することで簡単にサーバー側のプログラムを作成できる

import SocketServer

class MyClientHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        print(self.client_address, now())
        time.sleep(5)
        while True:
            data = self.request.recv(1024)
            if not data:
                break
            reply = 'Echo=>%s\' % data
            self.request.send(reply.encode())
        self.request.close()

if __name__=='__main__':
    myaddr = ('', 1234)
    server = SocketServer.ThreadingTCPServer(myaddr, MyClientHandler)
    server.serve_forever()

2012年10月15日月曜日

python - pickle モジュールによるバイナリデータ化


このエントリーをはてなブックマークに追加
バイナリデータにできる。保存やソケット通信などに利用。

import pickle

# 変換
binary_data = pickle.dumps(data)
data = pickle.loads(binary_data)

# ファイル書き込み
file = open('data.bin', 'wb')
pickle.dump(data, file)
file.close()

# ファイル読み込み
file = open('data.bin', 'rb')
data = pickle.loads(file)
file.close()

2012年10月14日日曜日

python - 正規表現


このエントリーをはてなブックマークに追加

re モジュールを使う
re.MULTILINE フラグを使わないと、行頭 ^ と行末 $ が、それぞれ改行の直後、改行の直前に引っかからないので注意。(文字列の先頭と終端のみに引っかかる)

  • re.search(pattern, text) : 一番最初のマッチを取ってくる
  • re.findall(pattern, text) :  全てのマッチを取ってくる
  • re.sub(pattern, sub, text) : pattern にマッチしたものを sub で置き換える

参考 : Python reモジュールで使える正規表現演算子

import re

filetext = open('list_inserter.hpp').read()
pattern = re.compile('#include\s+<.*$', re.MULTILINE)
print re.findall(pattern, filetext)

2012年10月13日土曜日

python - cygwin + Tkinter で "no display name and no $DISPLAY environment variable"


このエントリーをはてなブックマークに追加
参考 : Cannot launch git gui using cygwin on windows

[準備]

  • Cygwin の setup.exe で xinit と X-start-menu-icons をインストールする

[実行前]

  • Windows のスタートメニューから XWin Server を起動する
  • Cygwin のシェルで export DISPLAY=:0.0 と入力する or Python のスクリプト内で os.environ['DISPLAY'] = ':0.0' として環境変数を設定する

XWin Server を起動するのが少し面倒だし、そもそもインストールが必要なので他の人に使ってもらいづらい。

python - デフォルトプログラムでファイルを開く


このエントリーをはてなブックマークに追加
os.startfile('filename') を使う。

# txt ファイルを開く
os.startfile('text.txt')
# Webページを開く
os.startfile('https://www.google.co.jp/webhp?hl=ja')

2012年10月12日金曜日

python - modal ダイアログを作る


このエントリーをはてなブックマークに追加
grab_set() で他のウィンドウにイベントが届かないようにし
wait_window() で終了を待つ

win = TopLevel()
# ...
win.focus_set()
win.grab_set()
win.wait_window()

python - 可変長引数


このエントリーをはてなブックマークに追加

アスタリスク1つでキーワードなし(tuple)、
アスタリスク2つでキーワードあり(dictionary)

def flexible_tuple(*args):
    print args
   
def flexible_dict(**kwargs):
    print kwargs

def flexible(*args,**kwargs):  
    print args
    print kwargs


flexible_tuple('a', 1, 2)
flexible_dict(a=1,b=2,c='c',d=[1,2,3])
flexible('a',1,2,a=1,b=2,c='c',d=[1,2,3])

2012年10月11日木曜日

python - os.path.normpath と os.path.normcase


このエントリーをはてなブックマークに追加

パス名の比較、パスをキーにした辞書を作成する際等に使う。
  • os.path.normpath : 余分な区切り文字や上位レベル参照を削除し、パスの名前を標準化する。Windows ならスラッシュをバックスラッシュに変換する。
  • os.path.normcase : パス名の大文字、小文字をシステムの標準にする。 Windowsでは、スラッシュをバックスラッシュに変換する。