2016-08-03 3 views
5

Quelle est la bonne façon d'insérer les valeurs d'objets entiers numpy dans des bases de données dans python 3? En Python 2.7 Types de données numériques numpy insérer proprement dans SQLite, mais ils ne le font pas en python 3insertion de nombres entiers numpy dans sqlite avec python3

import numpy as np 
import sqlite3 
conn = sqlite3.connect(":memory:") 
conn.execute("CREATE TABLE foo (id INTEGER NOT NULL, primary key (id))") 
conn.execute("insert into foo values(?)", (np.int64(100),)) # <-- Fails in 3 

Les types np.float semblent fonctionner encore très bien à la fois 2 et 3.

conn.execute("insert into foo values(?)", (np.float64(101),)) 

En python 2, les types de nombres entiers scalaires numpy ne sont plus des instances de int, convertissant même des nombres à virgule flottante entiers en ints.

isinstance(np.int64(1), int) # <- true for 2, false for python 3 

Est-ce la raison pour laquelle le dbapi ne fonctionne plus de manière transparente avec numpy?

+0

Un type entier numpy est non seulement la représentation des octets du nombre (sa valeur '.item()'); est un objet, presque le même qu'un seul élément, 0d, tableau. Donc, je ne pense pas que vous pouvez le sauver, dans toute sa gloire numpy, dans une base de données. Vous pouvez enregistrer sa valeur entière, ou un équivalent en octets, mais pas l'objet numpy complet. Y at-il quelque chose dans 'sqlite3' concernant la sauvegarde d'une instance d'objet définie par l'utilisateur? – hpaulj

+0

Il y a toujours l'approche pickle effrayante (type TEXT de ciblage), ou quelque chose de plus moderne et binaire comme [MessagePack] (http://msgpack.org/) (ciblant le type BLOB). – sascha

+0

Quel est l'avantage d'enregistrer 'np.int64 (100)' au lieu de '100'? Y a-t-il des informations utiles que vous n'avez pas pu récupérer pendant un fetch? Vous pourriez regarder comment des modules comme SQLAlchemy gèrent l'interface sql-object. – hpaulj

Répondre

4

Selon sqlite3 docs:

Pour utiliser d'autres types de Python avec SQLite, vous devez les adapter à l'un des des types pris en charge du module sqlite3 pour SQLite: l'un des NoneType, int, float, str, octets.

Vous pouvez donc adapter Type np.int64. Vous devriez faire quelque chose comme ceci:

import numpy as np 
import sqlite3 

sqlite3.register_adapter(np.int64, lambda val: int(val)) 
conn = sqlite3.connect(":memory:") 
conn.execute("CREATE TABLE foo (id INTEGER NOT NULL, primary key (id))") 
conn.execute("insert into foo values(?)", (np.int64(100),)) 

Docs