1
0

More than 1 year has passed since last update.

Flask-SQLAlchemyで「could not convert string to float」エラー

Posted at

まえがき

PythonでFlask-SQLAlchemyを使っているときにエラーが発生して、解決に少し時間がかかったので備忘として記載します。
(解決してみれば非常に初歩的な事象でしたが...)

やろうとしたこと

Flask-SQLAlchemyでDB、テーブルを作成し、CSVから取り込んだ値を初期値として追加しようとしていました。

データは以下のような形です。

name(文字列) level(int) difficulty(float、空の場合がある)
ほげ 1 0.5
ふが 2
...

Modelは以下です。

Model
class Hoge(db.Model):
  id = db.Column(db.Integer, primary_key=True)
  name = db.Column(db.Text)
  level = db.Column(db.Integer)
  difficulty = db.Column(db.Float)

追加する部分のコードは以下です。

add.py
datalist = []
with open('data.csv', mode='r', encoding='utf-8') as f:
  tmp = csv.reader(f, delimiter=",", doublequote=True, lineterminator="\r\n", skipinitialspace=True)
  for i in tmp:
    datalist.append(i)

for i in datalist:
  h = Hoge(
    name = i[0],
    level = i[1],
    difficulty = i[2]
  )
  db.session.add(h)

エラー内容

sqlalchemy.exc.StatementError:
(raised as a result of Query-invoked autoflush; consider using a session.no_autoflush block if this flush is occurring prematurely)
(builtins.ValueError) could not convert string to float:
[SQL: INSERT INTO hoge (name, level, difficulty) VALUES (?, ?, ?)]
[parameters: [{'difficulty': '', 'name': 'ふが', 'level': '2'}]]

最初「sqlalchemy.exc.StatementError:(...)」の部分だけ見てしまい、これで検索して色々迷走していました...
本当に見るべきなのは以下でした。

(builtins.ValueError) could not convert string to float:
[SQL: INSERT INTO hoge (name, level, difficulty) VALUES (?, ?, ?)]
[parameters: [{'difficulty': '', 'name': 'ふが', 'level': '2'}]]

原因

could not convert string to floatはFlask-SQLAlchemy固有のエラーではなく、pythonのエラーです。
(builtinsと書いてありますね。私は見逃してました...)
このエラー事態は文字列からfloatに変換できない場合に表示されるようです。
(「1,000.5」のようにコンマがあると変換できない等)

今回の場合は、空の文字列をfloatに変換できずエラーとなっていたようでした。

改善方法

値を設定する部分に三項演算子を用いて、空の文字列がある場合はNoneを入力するように変更しました。

add.py
datalist = []
with open('data.csv', mode='r', encoding='utf-8') as f:
  tmp = csv.reader(f, delimiter=",", doublequote=True, lineterminator="\r\n", skipinitialspace=True)
  for i in tmp:
    datalist.append(i)

for i in datalist:
  h = Hoge(
    name = i[0],
    level = i[1],
    difficulty = i[2] if i[2] != '' else None # 変更
  )
  db.session.add(h)

これでエラー解消できました!

result.py
tmp = Hoge.query.all()
print(tmp)
print(tmp[0].__dict__)
結果
[<Hoge 1>, <Hoge 2>]
{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x000001AE0EF1F4E0>, 'id': 1, 'name': 'ほげ', 'difficulty': 0.5, 'level': 1}
{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x000001AE0EE76EF0>, 'name': 'ふが', 'level': '2', 'difficulty': None, 'id': 2}

補足

環境

OS:Windows10
pythonバージョン:3.7.3
Flaskバージョン:1.0.3
Flask-SQLAlchemyバージョン:2.5.1

本事象が再現できるコード

コード一覧を載せておきます。
Flask, Flask-SQLAlchemyの導入の仕方は各自調べてください。

app.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

class Hoge(db.Model):
  id = db.Column(db.Integer, primary_key=True)
  name = db.Column(db.Text)
  level = db.Column(db.Integer)
  difficulty = db.Column(db.Float)

db.create_all()

datalist = [['ほげ', '1', '0.5'], ['ふが', '2', '']]
for i in datalist:
  h = Hoge(
    name = i[0],
    level = i[1],
    difficulty = i[2]# if i[2] != '' else None # ここの三項演算子を有効にするとエラー解消します
  )
  db.session.add(h)

tmp = Hoge.query.all()
print(tmp)
print(tmp[0].__dict__)
print(tmp[1].__dict__)

参考元

三項演算子:https://qiita.com/howmuch515/items/bf6d21f603d9736fb4a5
could not convert string to floatエラー:https://engineeeer.com/python-convert-string-to-float/

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0