PythonスクリプトからcsvをmySQLに格納しているのですが、エラーが出てきて困っています。
自分が考えたところ、csvの中でダブルクォーテーションが出てきてそこでエラーが出てきていると思います。
なので、ダブルクォーテーションをエスケープシーケンスにしたいのですが、ダブルクーテーションのある文字列だけを取り出すことができません。
形式的には、コンマで区切られているcsvファイルが一行ずつリストに格納されている形です。
なので質問を成立すると、
文字列が格納されているリストから、ダブルクォーテーションが含まれる文字列を探し、データベースに格納できる形に変換したい。とゆうことです。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
![guest](/img/icon/icnUserSample.jpg)
回答3件
0
◇お願い!
1,質問文にMySQLを格納している部分のコードを記載してくださいな。
2,実行時エラーが発生しているのなら、そのエラー文字列もコピペで追記してくださいな。
手動でエスケープを行う方法については他の方が回答されてますので、
SQLインジェクション防止のために、SQLプレースホルダを使ったサンプルコードを投下しておきます。
◇プログラム構成
settings.json…dbの接続文字列をjsonファイルとして保持
data.csv…データベースに投入するcsvデータ
以下はサンプルコードです。
Python
1# -*- coding: utf8 -*- 2import csv 3from contextlib import closing 4import json 5import random 6# pip install mysql-connector-python-rf 7import mysql.connector 8 9# MySQLのDB名:testdbにデータを登録するサンプルです。 10 11 12def connect(): 13 with open('settings.json', encoding='utf-8-sig') as f: 14 json_data = json.load(f) 15 con_str = json_data['connection_strings'] 16 print(con_str) 17 return mysql.connector.connect(host=con_str['host'], db=con_str['db'], 18 user=con_str['user'], passwd=con_str['passwd'], 19 charset=con_str['charset']) 20 21 22def read_csv(file_name: str='data.csv', encoding='utf-8-sig'): 23 with open(file_name, encoding=encoding) as csv_file: 24 reader = csv.reader(csv_file) 25 # ↓ヘッダー行のスキップを行いたい時 26 #next(reader) 27 yield from reader 28 29 30def insert_data(cur) -> int: 31 random.seed(42) 32 row_count = 0 33 sql = f"insert into sample (id, rnd, item, qty) values (%s, %s, %s, %s)" 34 for i, rows in enumerate(read_csv()): 35 print(*rows) 36 rnd = random.randint(0, 500) 37 item = rows[0] 38 qty = rows[1] 39 params = (i, rnd, item, qty) 40 cur.execute(sql, params) 41 row_count += cur.rowcount 42 43 print(f"rowcount:{row_count}") 44 return row_count 45 46 47def select_data(cur) -> None: 48 sql = f"SELECT * FROM sample ORDER BY id" 49 print("#" * 40) 50 cur.execute(sql) 51 for row in cur.fetchall(): 52 print(row) 53 54 55def main() -> None: 56 with closing(connect()) as conn: 57 conn.ping(reconnect=True) 58 with closing(conn.cursor()) as cur: 59 # drop table 60 cur.execute(f"drop table if exists sample") 61 # create table 62 cur.execute(f"create table sample (id int, rnd int, item TEXT, qty int)") 63 # insert 64 insert_data(cur) 65 # select 66 select_data(cur) 67 # データベースへの変更を確定 68 conn.commit() 69 70 71if __name__ == '__main__': 72 main() 73
settings.json
json
1{"connection_strings":{"host":"localhost","db":"testdb","user":"root","passwd":"","charset":"utf8"}}
data.csv
txt
1"a"aa"a",10 2"bbbb",20 3"cccc",30 4"dddd",30
◇余談
csvからのデータ投入はプログラムを記述しなくてもDB側がバルクインサート機能としていろいろ用意していることが多いです。興味があるなら調べてみてくださいな。
MySQLはそこまで詳しくないですが、LOAD DATA INFILEが該当しそうです。(識者の方のコメント募集)
◇参考情報
Python 3 から MySQL を触る
投稿2018/03/27 20:46
編集2018/03/27 21:14総合スコア5846
0
ベストアンサー
とりあえず文字列のリストがあり、その中でダブルクオテーションを含む文字列とそうでない文字列がある、含む文字列のダブルクオテーションをSQLに入れられるようエスケープしたい、という状況でしょうか?
でしたら、次のような処理を書けば良いのではないでしょうか。
python
1>>> lst = ['"hoge"', 'fuga', 'piyo'] # ダブルクオテーションを含む文字列とそうでない文字列のリスト 2>>> lst2 = [s.replace('\"', '\"') for s in lst] 3>>> lst2 4['\"hoge\"', 'fuga', 'piyo']
なお、lst2の先頭要素「'"hoge"'」はバックスラッシュが二つ重なっているように見えますが、これは表示がエスケープされているからで、実際には1つです。
python
1>>> len(lst2[0]) 28 3>>> print(lst2[0]) 4\"hoge\"
具体的な状況があまりわからないので、もしかしたら的はずれな回答になっているかもしれません。その場合、もう少し詳しく現在の状況を教えて頂けるとより手助けできるかもしれません。
投稿2018/03/27 15:56
総合スコア30937
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。