Python3

Major Breakages 主な非互換部分
. Print function: print(a, b, file=sys.stderr) printが関数に
. Distinguish sharply btw. text and data テキストとバイナリデータを厳密に区別
. b"…" for bytes literals b"…" はバイト列のためのリテラル
. "…" for (Unicode) str literals "…" は文字列(Unicode文字列)のリテラル
. Dict keys() returns a set view [+items()/values()] 辞書の keys() は [+items()/values()] のビューを返す
. No default <, <=, >, >= implementation デフォルト実装の < <=, >, >= はなし
. 1/2 returns 0.5 1/2 の結果は 0.5
. Library cleanup ライブラリのクリンアップ

Long Anticipated Breakages 非互換部分のうち長く待ち望まれていたもの
. Kill classic classes classic classの削除
. Int/long unification Int と long の統一
. Kill string exceptions string exception の廃止
. Exceptions must subclass BaseException 例外は必ず BaseExceptionのサブクラスでなければならない
. Raise syntax: raise Exc(args) [from tb] raise Exc(args) [from tb] という raise構文
. Except syntax: except Exc as var: except Exc as var: という例外構文
. Also makes var undefined at block exit ブロックを抜けたときに変数を undefined にする

Many Small Breakages 多くの小規模な非互換
. Remove cmp() builtin ビルトインの cmp() はなくなりました
. Remove cmp arg to sorted() and list.sort() sorted() や list.sort() の引数としての cmp はなくなりました
. Kill map(None, …); use zip() map(None, …) はなくなりました。zip() を使ってください
. map(), filter() return iterators map() と filter()はイテレータを返します
. Disallow int(‘- 1’) int('- 1') は許されなくなりました
. Explicit relative import 明示的な相対パス指定による import
. Removed `…` `・・・` はなくなりました
. Removed <> <> はなくなりました
. None, True, False are keywords None, True, False は予約語になりました
. New keywords as, with, nonlocal 新しい予約語 as, with, nonlocal
. raw_input() -> input() raw_input() から input()へ
. xrange() -> range() xrange() から range()へ
. Changed metaclass syntax メタクラスの構文の変更
. Kill compiler package compiler パッケージの削除
. Kill tuple parameter unpacking タプルパラメータのアンパッキングの削除
. New octal literals (0o777) 新しい八進リテラル表記 0o777
. .next() -> .__next__(); next() built-in
nexxt() が __next__() に、新しい組み込みのものとしての next()
. .func_code -> .__code__ func_code が __code__ に
. Removed dict.has_key() dict.has_key() の削除
. Removed dict.iteritems() etc. dict.iteritems() などの削除
. Removed sys.maxint; use sys.maxsize sys.maxintの削除。sys.maxsizeを使ってください
. Removed reload(); use imp.reload() reload の削除。imp.reload()を使ってください
. Removed reduce(); use functools.reduce() reduce() の削除。functools.reduce()を使ってください
. Removed apply(); use f(*args) apply()の削除。f(*args)を使ってください
. Removed callable(); use Callable ABC callcable() の削除。Callable ABC を使ってください
. Removed basestring; use str basestring の削除。strを使ってください
. .__nonzero__() -> .__bool__()
. Etc, etc.

Transition Strategies 移行のための戦略
. If you can: burn your bridges! もし可能なら、退路を絶て!
. Otherwise: それができなければ
. Port to 2.6 first 2.6への移植を最初に
. Maintain 2.6 and 3.0 version together 2.6と3.0を一緒にメンテナンス
. Derive 3.0 version from 2.6 source 2.6向けのソースから3.0用のものを派生
. Using 2to3 whenever you can 使えるところであればどこでも 2to3 を使う
. Using forked code only where you have to 変換後のコードだけを使う
. Enables feature parity of your app or lib

あー、間違えてた

ケース2の場合だと、INSERT文が一括処理になっているから早くなっていたのか。

正確に比較するためには、

def func(i):
    print i
    Person(firstName="%s"%i, lastName="%s"%i)

for i in xrange(100):
  sqlhub.doInTransaction(func, i)

こうする必要があって、これだと速度はあんまり変わらなかった。あまりにも速度差がありすぎて怪しんでいたから納得。

SQLObjectを使ってsqliteを扱うときは、大量のデータを挿入する場合はトランザクションしないと使い物にならない

ここを参照して実験してみた。

例えば以下のようなトランザクションしない場合と、

  • ケース1
from sqlobject import *
import sys, os

db_filename = os.path.abspath('data.db')
if os.path.exists(db_filename):
  os.unlink(db_filename)

connection_string = 'sqlite:' + db_filename
connection = connectionForURI(connection_string)
sqlhub.processConnection = connection

class Person(SQLObject):
  firstName = StringCol()
  middleInitial = StringCol(length=1, default=None)
  lastName = StringCol()

Person._connection.debug = True

existDb = os.path.exists(db_filename)
if not existDb:
  Person.createTable()

for i in xrange(100):
  print i
  Person(firstName="%s"%i, lastName="%s"%i)

SQLObjectの機能を使ってトランザクションを行う場合を書いたとき、

  • ケース2
from sqlobject import *
import sys, os

db_filename = os.path.abspath('data.db')
if os.path.exists(db_filename):
  os.unlink(db_filename)

connection_string = 'sqlite:' + db_filename
connection = connectionForURI(connection_string)
sqlhub.processConnection = connection


class Person(SQLObject):
  firstName = StringCol()
  middleInitial = StringCol(length=1, default=None)
  lastName = StringCol()

existDb = os.path.exists(db_filename)
if not existDb:
  Person.createTable()

Person._connection.debug = True

def func():
  for i in xrange(100):
    print i
    Person(firstName="%s"%i, lastName="%s"%i)

sqlhub.doInTransaction(func)

ケース1は8秒かかるが、ケース2は0.5秒で終わる。SQLObjectを用いてSQLiteを操作するときはトランザクションを行わないと速度的に使い物にならない。