質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

9880閲覧

【Python】select結果をjosnファイルに出力したい

s_akira

総合スコア15

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/06/24 13:35

編集2018/06/25 02:35

select結果を辞書型に出力する際の順番の指定方法について質問させていただきたいです。

下記のコード状態で、実行するとselect取得結果がテーブルカラムの順番とは違った形で出力されてしまいます。
selectで取得した結果(カラムの順番のまま)を、ファイルに出力したのですがどうしたらいいでしょうか。
※7行目の"dict"で順番が変更されてしまっていると思います。

コメントアウトした箇所を変更しましたら、順番がselectのとおりとなりました。(ありがとうございます。)
が、ファイル出力には、カラム名が出力されない状態です。

Python

1conn = psycopg2.connect(hostとかの設定) 2cur = conn.cursor(cursor_factory=psycopg2.extras.NamedTupleCursor) 3#cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor) 4 5cur.execute("SELECT カラム1, カラム2, カラム3, カラム4 from test") 6#またはこっち 7#cur.execute("SELECT * from test") 8results = cur.fetchall() 9 10dict_result = [] 11for row in results: 12 dict_result.append(row._asdict()) 13 #dict_result.append(dict(row)) 14 15with open(filename, "w") as f: 16 json.dump(results, f, indent=4)

以下のようなテーブルがあったとして、実行すると順番がカラム1〜4と順番の通りに出力さず順番がシャッフルされます。

カラム1カラム2カラム3カラム4
ABCD

を上記コードで実行すると、以下のような感じでバラバラにされてしまいます。(ファイル出力時)

"カラム2": "B",
"カラム1": "A",
"カラム4": "D",
"カラム3": "C"

printすると以下で表示されています。
[Record(column1='A ', column2='B ', column3='C ', column4='D ')]

これを、以下のようにテーブルのカラムの順番で表示させたいです。

”カラム1":"A",
”カラム2":"B",
”カラム3":"C",
"カラム4":"D"

検索をかけているのですがうまくいきません。以下、参考にしているURLです。
Pythonでリスト(配列)に要素を追加
Python psycopg2 で dict形式で結果を取得
Pythonで辞書を作成するdict()と波括弧、辞書内包表記

すみませんが、よろしくお願い致します。

〜備考〜
・言語:Python
・DB:postgresql
・Create文:
create table test (
column1 character(10)
,column2 character(10)
,column3 character(10)
,column4 character(10)
)
・insert文
insert INTO test (
column1,
column2,
column3,
column4
)
VALUES
( 'A',
'B',
'C',
'D'
)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

LouiS0616

2018/06/24 13:46

『以下のような感じ』とのことですが、本当に {"カラム1:A" ...} となっているのでしょうか。実際には {"カラム1": "A", ...} となっていたりしませんか?
s_akira

2018/06/24 14:19

Orlofskyさん > すみません、修正しました。
s_akira

2018/06/24 14:20

LouiS0616さん > 重要な箇所ミスしてしまいもうしわけありません。おっしゃるとおりです。
umyu

2018/06/24 14:57 編集

今回の問題とは関係ありませんが、出力順を保証する必要があるのであればSELECT句にはORDER BY句を指定してくださいな。
s_akira

2018/06/25 02:39

umyuさん > ご回答ありがとうございます、わかりました。
guest

回答3

0

ベストアンサー

実は、Python3.5以下のdictは挿入した順番が維持されません。なので、順番を保持するにはcollentionsモジュールのOrderedDictを使う必要があります。
How to preserve column order while using psycopg2.extras.RealDictCursor
ここに詳しいですが、2行目cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)の代わりにpsycopg2.extras.NamedTupleCursorをつかって、7行目でdict_result.append(dict(row))dict_result.append(row._asdict())とすればよいかと思います。

投稿2018/06/24 14:37

編集2018/06/24 22:53
frodo821

総合スコア322

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

s_akira

2018/06/24 16:19

まだ、調査中なのですが。。解決できないため 下記でエラーが出てしまいました・・・ cur = conn.cursor(psycopg2.extras.NamedTupleCursor) TypeError: Expected bytes or unicode string, got type instead すみませんがなにかアドバイスありましたら教えていただけないでしょうか。
frodo821

2018/06/24 16:26

cur = conn.cursor(cursor_factory=psycopg2.extras.NamedTupleCursor) に書き換えてみてください。
s_akira

2018/06/24 16:55

上記に変更して、実行しましたら、 print(results)をするとほしい順番にでることができました!ありがとうございます! ファイル出力でカラムが出力されなくてうまくいっていませんのでもう少し調べてみます。
frodo821

2018/06/24 22:50

ファイル出力でカラムが出力されないとは、具体的にどういう状況なのでしょうか?
s_akira

2018/06/25 02:38 編集

何度も申し訳ありません。 質問コードのファイル出力すると、下記のようになります。 [ [ "A ", "B ", "C ", "D " ] ] が表示される状態です。A,B,C,Dの後ろに謎の空白もまざっており、確実に簡単なミスかとは思うのですが。。。 print(results)をすると、[Record(column1='A ', column2='B ', column3='C ', column4='D ')]となっています。
s_akira

2018/06/25 02:53

frodo821さん 何度もコメント申し訳ありません。 json.dump(results, f, indent=4) が誤っておりました。 正しくは、json.dump(dict_result, f, indent=4)でした。 と修正したところほしい結果(以下)が出力されました。 [ { "column1": "A ", "column2": "B ", "column3": "C ", "column4": "D " } ] A,B,C,Dの後ろに謎の空白が入ってしまっていますが一旦出力できました。 本当にありがとうございます。
guest

0

ソートしたい順に order by するだけで良いのでは?

SQL

1cur.execute("SELECT カラム1, カラム2, カラム3, カラム4 from test") 23cur.execute("SELECT カラム1, カラム2, カラム3, カラム4 from test order by カラム1, カラム2, カラム3, カラム4")

投稿2018/06/24 16:59

Orlofsky

総合スコア16415

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

s_akira

2018/06/24 17:16

ご回答ありがとうございます! order byをしただけですと、辞書型のせいかなぜか順番が制御できませんでした…
Orlofsky

2018/06/24 17:20

問題が速やかに解決できるように、質問にSQLで使っているテーブルのCREATE TABLE文も載せては?
s_akira

2018/06/25 02:36

追加してみました。ご指摘ありがとうございます。
guest

0

jsonモジュールのドキュメントを見なおしたら、もっとまともな解決法がありました。

書き出し時

json.dump(...)
sort_keys が true (デフォルトでは False です)であれば、辞書の出力がキーでソートされます。

Python

1import json 2 3results = { 4 "column2": "B", 5 "column1": "A", 6 "column4": "D", 7 "column3": "C" 8} 9 10with open('out.json', 'w') as f: 11 json.dump(results, f, sort_keys=True)

読み出し時

json.load(...)
object_pairs_hook はオプションで渡す関数で、ペアの順序付きリストのデコード結果に対して呼ばれます。 object_pairs_hook の返り値は dict の代わりに使われます。この機能はキーと値のデコードされる順序に依存する独自のデコーダ (たとえば collections.OrderedDict() は挿入の順序を記憶します) を実装するのに使えます。

Python

1from collections import OrderedDict 2import json 3 4with open('out.json') as f: 5 data = json.load(f, object_pairs_hook=OrderedDict) 6 7print(data)

旧回答

SQLは触ったことがないので、見当違いなことを言っていたらすみません。


一般に辞書構造は順序を保証しませんので、二重リストとして出力するのが妥当かと。
追記: 書き出し時/読み出し時に充分な配慮があれば辞書構造でも良いようです。

オブジェクトは、順序付けされない名前/値のペアのセットです。
配列は、順序付けされた値の集まりです。

引用元: JSON の紹介

Python

1import json 2 3results = { 4 "column2": "B", 5 "column1": "A", 6 "column4": "D", 7 "column3": "C" 8} 9 10results_list = [] 11for key in sorted(results.keys()): 12 results_list.append( 13 [key, results[key]] 14 ) 15 16# 内包表記を使う場合 17# results_list = [[key, results[key]] for key in sorted(results.keys())] 18 19print(results_list) # [['column1', 'A'], ['column2', 'B'], ['column3', 'C'], ['column4', 'D']] 20 21with open('out.json', 'w') as f: 22 json.dump(results_list, f)

投稿2018/06/24 14:34

編集2018/06/25 07:53
LouiS0616

総合スコア35658

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

s_akira

2018/06/25 02:41

ご回答ありがとうございます。 listのkey箇所で以下、エラーがでてしまう状態で。。。 AttributeError: 'list' object has no attribute 'keys' もう少し調査していろいろしてみます!
LouiS0616

2018/06/25 02:57 編集

SQLでリスト形式でデータを受け取れるならそれに越したことはないです。 --- 私に分かるのは次の二点です。 ・Pythonで一瞬でも組み込み辞書として扱うと順序は保証できない ・jsonにオブジェクト形式で出力しても順序は保証できない
s_akira

2018/06/25 07:17

LouiS0616さん 承知いたしました。 ご教示いただき、ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問