PostgreSQLで指定テーブルのみdumpする
よく忘れてしまうpg_dumpで指定テーブルのみdumpする方法のメモです。
この際は PostgreSQL 9.3.9 を利用しました。
指定テーブルのみdump
pg_dump --username=username --table table_name db_name > table_name.sql
指定テーブルのデータのみdump
pg_dump --username=username --data-only --table table_name db_name > table_name.sql
指定テーブルのスキーマのみdump
pg_dump --username=username --schema-only --table table_name db_name > table_name.sql
dumpしたデータを取り込む(SQL実行)
psql --username=username db_name < table_name.sql
PostgreSQLにおけるUNIQUE制約とUNIQUE INDEXの違い?
正直なところ勘違いをしていました。UNIQUEの制限をするためにUNIQUE INDEXをしばしば作成していましたので、この違いを調べました。
PostgreSQL 9.3.9においては、
- UNIQUE 制約を作ると UNIQUE INDEX も作られるが、
- UNIQUE INDEX を作っても UNIQUE 制約 は作られないようです。
そのためinformation_schema.table_constraints
テーブルに差が現われます。ただし、エラーメッセージは同じようです。
UNIQUE 制約( CREATE TABLE 時)
- 作成
CREATE TABLE example1 ( id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL, date DATE DEFAULT CURRENT_DATE NOT NULL, UNIQUE(user_id, date) );
制約確認
SELECT constraint_name, table_name, constraint_type FROM information_schema.table_constraints WHERE table_schema = 'public' AND table_name = 'example1'
- 結果
constraint_name | table_name | constraint_type |
---|---|---|
example1_pkey | example1 | PRIMARY KEY |
example1_user_id_date_key | example1 | UNIQUE |
※NOT NULL制約は省略
INDEX確認
SELECT tablename, indexname, indexdef FROM pg_indexes WHERE tablename = 'example1';
- 結果
tablename | indexname | indexdef |
---|---|---|
example1 | example1_pkey | CREATE UNIQUE INDEX example1_pkey ON example1 USING btree (id) |
example1 | example1_user_id_date_key | CREATE UNIQUE INDEX example1_user_id_date_key ON example1 USING btree (user_id, date) |
エラー確認
INSERT INTO example1(user_id, date) VALUES(1, CURRENT_DATE), (1, CURRENT_DATE);
- エラーメッセージ
ERROR: 重複キーが一意性制約"example1_user_id_date_key"に違反しています
UNIQUE 制約( CREATE TABLE 後 ALTER TABLE で追加)
- 作成
CREATE TABLE example2 ( id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL, date DATE DEFAULT CURRENT_DATE NOT NULL ); ALTER TABLE example2 ADD UNIQUE(user_id, date);
制約確認
SELECT constraint_name, table_name, constraint_type FROM information_schema.table_constraints WHERE table_schema = 'public' AND table_name = 'example2'
- 結果
constraint_name | table_name | constraint_type |
---|---|---|
example2_pkey | example2 | PRIMARY KEY |
example2_user_id_date_key | example2 | UNIQUE |
※NOT NULL制約は省略
INDEX確認
SELECT tablename, indexname, indexdef FROM pg_indexes WHERE tablename = 'example2';
- 結果
tablename | indexname | indexdef |
---|---|---|
example2 | example2_pkey | CREATE UNIQUE INDEX example2_pkey ON example2 USING btree (id) |
example2 | example2_user_id_date_key | CREATE UNIQUE INDEX example2_user_id_date_key ON example2 USING btree (user_id, date) |
エラー確認
INSERT INTO example2(user_id, date) VALUES(1, CURRENT_DATE), (1, CURRENT_DATE);
- エラーメッセージ
ERROR: 重複キーが一意性制約"example2_user_id_date_key"に違反しています
UNIQUE INDEX
- 作成
CREATE TABLE example3 ( id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL, date DATE DEFAULT CURRENT_DATE NOT NULL ); CREATE UNIQUE INDEX example3_user_id_date_key ON example3(user_id, date);
制約確認
SELECT constraint_name, table_name, constraint_type FROM information_schema.table_constraints WHERE table_schema = 'public' AND table_name = 'example3'
- 結果
constraint_name | table_name | constraint_type |
---|---|---|
example3_pkey | example3 | PRIMARY KEY |
※NOT NULL制約は省略
INDEX確認
SELECT tablename, indexname, indexdef FROM pg_indexes WHERE tablename = 'example3';
- 結果
tablename | indexname | indexdef |
---|---|---|
example3 | example3_pkey | CREATE UNIQUE INDEX example3_pkey ON example3 USING btree (id) |
example3 | example3_user_id_date_key | CREATE UNIQUE INDEX example3_user_id_date_key ON example3 USING btree (user_id, date) |
エラー確認
INSERT INTO example3(user_id, date) VALUES(1, CURRENT_DATE), (1, CURRENT_DATE);
- エラーメッセージ
ERROR: 重複キーが一意性制約"example3_user_id_date_key"に違反しています
Threejs r76で球体&パーティクル
Threejsのr76を用いて球体とパーティクルに挑戦した際のメモです。
こちらのサイトを参考にしました。
手順としてあっているかどうかわかりませんが、前面部分だけパーティクルを描画して欲しかったのでSphereGeometry
をMeshBasicMaterial
にて単色で塗りつぶした上でパーティクルの描画を行っています。
- 単色(
#666699
)で塗りつぶした球体をsceneに追加
var sphere = new THREE.Mesh( new THREE.SphereGeometry(200, 100, 100), new THREE.MeshBasicMaterial({ color: 0x666699 }) ); this.scene.add(sphere);
- その後
Points
を用意してsceneに追加
this.particles = new THREE.Points( sphere.geometry, new THREE.PointsMaterial({ size: 3, color: 0xFFFFFF }) ); this.scene.add(this.particles);
これらのサイトを参考にしました。
画面奥に向かって背面にあたる部分のパーティクルは見えなくなり透けている感はなくなりました。
デモはこちらです。
Python3でPyOCRを用いてPacerのシェア画像から歩数抽出
Pacer(iOS, Android)という歩数管理のアプリではTwitterやFacebookに歩数などの記録を画像としてシェアできます。今回はその画像から文字部分を抽出して文字として認識可能なように挑戦したもので、環境は Windows 7, Python 3.5.1 です。
Pacerでシェアした抽出対象の画像
- 当初種類1に分類している画像を利用していましたが、日付が入っていないので種類2に分類している画像を利用するようにしました。
iPhone SEでキャプチャした画像
種類1 | 種類2 |
---|---|
1.jpg | 2.jpg |
3.jpg | 4.jpg |
Windowsなので付属のペイントでルーラー
とグリッド線
を有効にして座標を確認
- 赤枠の部分が抽出対象です。
必要なアプリケーション及びPythonモジュールを用意
Tesseract-OCR
- 画像から文字列を抽出するにあたり、OCRを利用します。
https://github.com/tesseract-ocr/tesseract#installing-tesseract - 抽出対象が数字やアルファベットの場合、日本語辞書は必要ありません。
PyOCR, PIL, numpy
- Pythonから上記OCRを利用するモジュールpyocrを利用しています。
- 画像操作でPIL(Pillow)が必要になります。
- 画像を2値化する際numpyを利用しています。
- インストール時点のバージョンはそれぞれ pyocr (0.4.2), Pillow (3.4.2), numpy (1.11.2) です。
Windows
python -m pip install pyocr python -m pip install Pillow python -m pip install numpy
LinuxやmacOS
pip install pyocr pip install Pillow pip install numpy
コード
- 当初全体から抽出を試みたものの、どこからどこまでが何の情報かわからないので対象部分を切り抜いてから文字抽出を試みるのが良さそうです。
- カラー画像だと抽出精度が低くなるようなので2値化しています。
# -*- encoding: utf-8 -*- from PIL import Image, ImageDraw import numpy, os, pyocr, pyocr.builders, re, sys tools = pyocr.get_available_tools() if len(tools) == 0: sys.exit('Not Found OCR tools') MIN_COLOR = 0 MAX_COLOR = 255 def retrieveStr(image_path): result = {} # 画像読み込み img = Image.open(image_path) # 文字を認識しやすいよう閾値200で白か黒の2値に変換 array = numpy.asarray(img.convert('L')) array.flags.writeable = True w, h = img.size for y in range(h): for x in range(w): array[y, x] = MAX_COLOR if (array[y, x] > 200) else MIN_COLOR img = Image.fromarray(numpy.uint8(array)) positions = {} # 1ピクセル目のRGBで画像種類を判断 r, g, b = img.crop((0, 0, 1, 1)).convert('RGB').getpixel((0, 0)) if r == MAX_COLOR: # 活動時間 positions['active time'] = (190, 70, 440, 140) # カロリー positions['calories'] = (10, 70, 170, 140) # Km positions['km'] = (450, 70, 630, 140) # 歩数 positions['steps'] = (170, 280, 470, 390) else: # 活動時間 positions['active time'] = (220, 410, 420, 460) # カロリー positions['calories'] = (80, 410, 210, 460) # 日付 positions['date'] = (190, 130, 450, 165) # Km positions['km'] = (430, 410, 560, 460) # 歩数 positions['steps'] = (220, 220, 440, 300) # 日本語辞書を使わないので`年月日`を塗りつぶす dr = ImageDraw.Draw(img) # [(始点x,始点y),(終点x,終点y)],fill=塗つぶし色 dr.rectangle([(275, 130), (305, 160)], fill=MAX_COLOR) # 年 dr.rectangle([(340, 130), (365, 160)], fill=MAX_COLOR) # 月 dr.rectangle([(405, 130), (430, 160)], fill=MAX_COLOR) # 日 for label, pos in positions.items(): # 欲しい部分だけ画像を切り抜く im = img.crop(pos) # 拡大縮小 # im.thumbnail((im.size[0] / 3, im.size[1] / 3), Image.ANTIALIAS) # im = im.resize((im.size[0] * 3, im.size[1] * 3)) # 画像表示 # im.show() # 画像から文字抽出 text = tools[0].image_to_string( im, builder=pyocr.builders.TextBuilder(tesseract_layout=6) ) # バイト列をUTF-8でエンコードしてUTF-8の文字列にデコード text = text.encode('utf_8').decode('utf_8') # 時間を取り出して秒に変える if label == 'active time': at = re.split('[^\d]+', text)[:-1] hours = 0 if len(at) == 1 else int(at[0]) minutes = int(at[len(at) - 1]) text = (hours * 60 * 60) + (minutes * 60) # str -> int elif label == 'calories': text = int(text) # 日付整理 elif label == 'date': text = '-'.join(re.split('[^\d]+', text)) # str -> float elif label == 'km': text = float(text) # 数字以外の文字を詰める elif label == 'steps': text = int(''.join(re.split('[^\d]+', text))) result[label] = text return result if __name__ == '__main__': base_dir = os.path.dirname(__file__) if not base_dir: base_dir = '.' img_dir = base_dir + os.path.sep + 'img' + os.path.sep for i in range(4): res = retrieveStr(img_dir + str(i + 1) + '.jpg') for val in res.items(): print('{}: {}'.format(*val)) print()
結果
c:\>python C:\py\ocr\img.py steps: 17589 active time: 9300 km: 13.9 calories: 640 date: 2016-10-31 steps: 18709 active time: 10140 km: 15.0 calories: 685 steps: 42177 active time: 22080 km: 33.4 calories: 1449 date: 2016-11-01 steps: 11488 active time: 6720 km: 9.0 calories: 390 c:\>
参考
Python3でPycURLを用いてteratail APIのJSONからPythonタグつきの質問を取得
teratailというプログラミングQ&AサイトのAPIからJSON形式で質問取得を試みた際のメモです。Pythonで試みたのでPythonに関連する質問の取得を試みています。環境は Windows 7, Python 3.5.1 です。
必要なPythonモジュールを用意
PycURL
- PythonでcURLライブラリを使うモジュールを利用しています。
今回はHTTP(S)リクエストする際に用います。
PHPを使ったことがあれば、PHPのcurl関数のような感じで利用できるイメージです。 - この際にインストールしたバージョンは pycurl (7.43.0) です。
Windows
python -m pip install pycurl
LinuxやmacOS
pip install pycurl
コード
BEARER = ''
でteratailに登録後取得できるアクセストークンを設定します。- 無くても動作しますがteratailの仕様で1時間あたり30回までのアクセスになるそうです。アクセストークンがあれば1時間あたり300回までアクセス可能になるそうです。
# -*- encoding: utf-8 -*- import io, json, pycurl, sys, urllib.parse if __name__ != '__main__': sys.exit() # teratail登録後、 https://teratail.com/users/setting/tokens で取得 BEARER = '' class Teratail: API_URL = 'https://teratail.com/api/v1/tags/{}/questions?limit={}&page={}' __curl = None __tag = '' __limit = 20 __page = 1 __bearer = None __httpCode = 200 def __init__(self, tag='', limit=20, page=1): self.__tag = tag self.__limit = limit self.__page = page # インスタンス生成 self.__curl = pycurl.Curl() def __execute(self): json = None buf = io.BytesIO() headers = {} if self.__bearer: headers['Authorization'] = 'Bearer {}'.format(self.__bearer) self.__curl.reset() try: # Headerをセット headers = ['{}: {}'.format(*v) for v in headers.items()] self.__curl.setopt(pycurl.HTTPHEADER, headers) # リクエスト先をセット self.__curl.setopt(pycurl.URL, self.API_URL.format(self.__tag, self.__limit, self.__page)) # MethodをGETにセット(デフォルト) #self.__curl.setopt(pycurl.CUSTOMREQUEST, 'GET') # SSL証明書の有効性を確認しない self.__curl.setopt(pycurl.SSL_VERIFYPEER, False) # pycurlの結果を変数に格納 self.__curl.setopt(pycurl.WRITEDATA, buf) # 出力 self.__curl.perform() # 取得したjsonデータをUTF-8にデコード json = buf.getvalue().decode('UTF-8') except (pycurl.error, TypeError): pass self.__httpCode = self.__curl.getinfo(pycurl.HTTP_CODE) buf.close() return json def setBearer(self, bearer): self.__bearer = bearer def getHttpCode(self): return self.__httpCode # http://docs.teratailv1.apiary.io/#introduction def getJson(self, tag=None, limit=None, page=None): if tag is not None: self.__tag = tag if limit is not None: self.__limit = limit if page is not None: self.__page = page return self.__execute() tt = Teratail(limit=5) tt.setBearer(BEARER) # http://docs.teratailv1.apiary.io/#reference/(tag)/2/0 for tag in ('Python', 'Python 2.7', 'Python 3.x'): print(tag) jsonData = tt.getJson(tag=urllib.parse.quote_plus(tag)) if jsonData is None: continue data = json.loads(jsonData) if 'questions' not in data: if 'meta' in data and 'message' in data['meta']: print('HTTP Status Code: {}'.format(tt.getHttpCode())) print('Message: {message}'.format(**data['meta'])) continue print('Data:') for row in data['questions']: if 'id' not in row: continue # 質問ページ print('https://teratail.com/questions/{id}'.format(**row)) # 質問のタイトル print(row['title'] if 'title' in row else None) # 質問を投稿したユーザの名前 if 'user' in row and 'display_name' in row['user']: print(row['user']['display_name']) print() print()
jQuery: .each()に渡すfunctionの第1引数には連番が渡される
- 次のようにわざわざ番号を数えるような処理にしてしまうことがありますが…。
- .each()に渡すcallback functionの第1引数には0から順にカウントアップするindexが渡されているので次のような処理で十分です。
次のようにわざわざ番号を数えるような処理にしてしまうことがありますが…。
サンプルコード
<html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script> <script> $(function(){ var i = 0; $('.element').each(function(){ console.log(i++); }); }); </script> </head> <body> <div> <span class="element"></span> <span class="element"></span> <span class="element"></span> </div> </body> </html>
javascriptのみ抜粋
var i = 0; $('.element').each(function(){ console.log(i++); });
結果
0 1 2
.each()
に渡すcallback functionの第1引数には0から順にカウントアップするindexが渡されているので次のような処理で十分です。
サンプルコード
<html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script> <script> $(function(){ $('.element').each(function(i){ console.log(i); }); }); </script> </head> <body> <div> <span class="element"></span> <span class="element"></span> <span class="element"></span> </div> </body> </html>
javascriptのみ抜粋
$('.element').each(function(i){ console.log(i); });
結果
0 1 2
Python 3.5.1でクラスを試す
- クラスのサンプル
- インスタンス生成で __init__ が呼ばれる
- with文で __enter__, __exit__ が呼ばれる
- for文で __iter__ が呼ばれる
- クラスのインスタンスオブジェクトのメソッド(インスタンス変数へアクセス可)
- クラスメソッド(インスタンス変数へはアクセス出来ない)
- スタティックメソッド(インスタンス変数へはアクセス出来ない)
- スクリプト終了で __del__ が呼ばれる
- メソッド名はどのように確認する?
- 行番号はどのように確認する?
クラスのサンプル
- Pythonのクラスは、PHPと異なりメソッドの第1引数に毎回
self
と書く必要があったりするようです。 - メソッドやクラス変数の
protected
,private
などのアクセス権はPythonには無いようです。 - 参考: Python チュートリアル クラス
# -*- encoding: utf-8 -*- import inspect, sys class Example: test = None # コンストラクタ def __init__(self): self.test = 'hoge' print(sys._getframe().f_code.co_name) print() # デストラクタ def __del__(self): print(sys._getframe().f_code.co_name) print() # with文の始め def __enter__(self): print(sys._getframe().f_code.co_name) print() # with ~ as 変数にインスタンスを格納する際に必要 return self # with文の終わり def __exit__(self, exc_type, exc_value, traceback): print(exc_type, exc_value, traceback) print(sys._getframe().f_code.co_name) print() # ジェネレータ def __iter__(self): print(sys._getframe().f_code.co_name) for i in range(10): yield i # クラスのインスタンスオブジェクトのメソッド # 第1引数に`self` def instance_method(self, *params): print(self.test) print(params) print(sys._getframe().f_code.co_name) print() # クラスメソッド @classmethod def class_methos(*params): print(params) print(sys._getframe().f_code.co_name) print() # スタティックメソッド @staticmethod def static_method(*params): print(params) print(sys._getframe().f_code.co_name) print()
インスタンス生成で __init__
が呼ばれる
- クラスのサンプルから抜粋
# コンストラクタ def __init__(self): self.test = 'hoge' print(sys._getframe().f_code.co_name) print()
- 実行した場合
e = Example() # __init__ が出力される
sys._getframe().f_code.co_name
でメソッド名を取得しています。
メソッド名はどのように確認する?
with文で __enter__
, __exit__
が呼ばれる
- クラスのサンプルから抜粋
# with文の始め def __enter__(self): print(sys._getframe().f_code.co_name) print() # with ~ as 変数にインスタンスを格納する際に必要 return self # with文の終わり def __exit__(self, exc_type, exc_value, traceback): print(exc_type, exc_value, traceback) print(sys._getframe().f_code.co_name) print()
- 実行した場合
with e as instance: # __enter__ が出力される print(instance) # __enter__ で self を return していないと None # with文が終了すると __exit__ が出力される
- これは、ファイルを開くときなどの形ですね。
with open('text.txt') as f: for line in f: pass
for文で __iter__
が呼ばれる
- クラスのサンプルから抜粋
# ジェネレータ def __iter__(self): print(sys._getframe().f_code.co_name) for i in range(10): yield i
- 実行した場合
print(', '.join([str(i) for i in e])) print() # __iter__ が出力され、 # __iter__ からの結果をリスト化し', 'でjoinして 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 を出力
- 参考:
クラスのインスタンスオブジェクトのメソッド(インスタンス変数へアクセス可)
直接も呼べますが、インスタンス変数へはアクセス出来ません
- クラスのサンプルから抜粋
# クラスのインスタンスオブジェクトのメソッド # 第1引数に`self` def instance_method(self, *params): print(self.test) print(params) print(sys._getframe().f_code.co_name) print()
- 実行した場合
e.instance_method(inspect.getouterframes(inspect.currentframe())[0].lineno) # hoge # __init__ で代入した値を出力 # (74,) # 行番号 # instance_method
inspect.getouterframes(inspect.currentframe())[0].lineno
で行番号を取得しています。
行番号はどのように確認する?
クラスメソッド(インスタンス変数へはアクセス出来ない)
インスタンスからも呼べますが、インスタンス変数へはアクセス出来ません
- クラスのサンプルから抜粋
@classmethod
というデコレータなる仕組みがポイントになるようです。
# クラスメソッド @classmethod def class_methos(*params): print(params) print(sys._getframe().f_code.co_name) print()
- 実行した場合
Example.class_methos(inspect.getouterframes(inspect.currentframe())[0].lineno) # (<class '__main__.Example'>, 78) # 行番号は第2引数に渡されている # class_methos
- 参考:
スタティックメソッド(インスタンス変数へはアクセス出来ない)
インスタンスからも呼べますが、インスタンス変数へはアクセス出来ません
- クラスのサンプルから抜粋
@staticmethod
というデコレータなる仕組みがポイントになるようです。
# スタティックメソッド @staticmethod def static_method(*params): print(params) print(sys._getframe().f_code.co_name) print()
- 実行した場合
Example.static_method(inspect.getouterframes(inspect.currentframe())[0].lineno) # (82,) # 行番号 # static_method
スクリプト終了で __del__
が呼ばれる
- クラスのサンプルから抜粋
# デストラクタ def __del__(self): print(sys._getframe().f_code.co_name) print()
- 実行した場合
# スクリプト終了直前に __del__ が出力される
- ガーベージコレクト任せになってしまい任意のタイミングに処理されるかどうかわからないため、
__enter__
,__exit__
によるwith文の方が扱いやすいようです。
メソッド名はどのように確認する?
PHPだと__FUNCTION__
で確認できるメソッド名は、Pythonだとsys._getframe().f_code.co_name
で確認できるようです。
- 参考:
行番号はどのように確認する?
PHPだと__LINE__
で確認できる行番号は、Pythonだとinspect.getouterframes(inspect.currentframe())[0].lineno
で確認できるようですが、バージョンによって少し異なるようです。今回はPython 3.5.1です。
- 参考: