2016-03-21 1 views
1

Beim Versuch, Benutzerdaten von einer JSON-Datei in eine Datenbank mit der SQLAlchemy Ausdruckssprache zu importieren, erhalte ich die Fehlermeldung: NameError: name 'users' is not defined„Nameerror: name‚<tableName>‘ist nicht definiert“ in SQLAlchemy wenn Importieren von Daten

Der Traceback ist wie folgt:

Traceback (most recent call last): 
    File  "C:\Users\lmills\MyProject\Database-Configuration\CreateTable.py", line 43, in <module> 
    importData.userDataImport() 
    File  "C:\Users\lmills\MyProject\Database-Configuration\importData.py", line 11, in userDataImport 
    conn.execute(users.insert(), userid = userData[i]['userid'], altuid = userData[i]['altuid'], lname = userData[i]['lname'], fname = userData[i]['fname'], phoneNum = userData[i]['phoneNum'], emailAddr = userData[i]['emailAddr']) 
NameError: name 'users' is not defined 

I Ausgabe der Tabellen Anweisungen in einem Python-Programm erstellen, CreateTable.py:

from sqlalchemy import create_engine, Table, Column, Integer, String,  
MetaData, ForeignKey 
import importData 
import json 

engine = create_engine('sqlite:///MyProject.db', echo=True) 
metadata = MetaData(engine) 

metadata.drop_all(engine) 

users = Table('users', metadata, 
    Column('userid', Integer, primary_key=True), 
    Column('altuid', String(12)), 
    Column('lname', String(32)), 
    Column('fname', String(32)), 
    Column('phone_num', Integer, nullable=False), 
    Column('email_addr', String(32), nullable=False), 
) 

subscribables = Table('subscribables', metadata, 
    Column('subtag', Integer, primary_key=True), 
    Column('message_template', String(64)), 
    Column('descriptor_string', String(64)), 
) 

user_subs = Table('user_subs', metadata, 
    Column('userid', Integer, ForeignKey('users.userid')), 
    Column('subtag', Integer, ForeignKey('subscribables.subtag')), 
) 

user_prefs = Table('user_prefs', metadata, 
    Column('userid', Integer, ForeignKey('users.userid')), 
    Column('type_id', String(8), ForeignKey('notification_type.type_id')), 
) 

notification_type = Table('notification_type', metadata, 
    Column('type_id', String(8), primary_key=True), 
    Column('typename', String(8), nullable=False), 
    Column('Template', String(64)), 
) 

metadata.create_all() 

importData.userDataImport() 

Dann versuche ich, Daten zu importieren, ein Modul verwenden, userDataImport, innerhalb der importData.py-Datei, die die folgenden enthält:

import json 
from sqlalchemy import create_engine 
import sqlalchemy 

def userDataImport(): 
    engine = create_engine('sqlite:///MyProject.db', echo=True) 
    conn = engine.connect() 
    with open(r'C:\Users\lmills\MyProject\userData.json') as dataFile: 
     userData = json.load(dataFile) 
      for i in range(len(userData)): 
       conn.execute(users.insert(), userid = userData[i]['userid'], altuid = userData[i]['altuid'], lname = userData[i]['lname'], fname = userData[i]['fname'], phoneNum = userData[i]['phoneNum'], emailAddr = userData[i]['emailAddr']) 

if __name__ == "__main__": userDataImport() 

jedoch SQLAlchemy können Benutzer nicht identifizieren, die in der Tabelle ist, die ich in CreateTable.py geschaffen hatte, Wenn ich den Code aus dem Modul "userDataImport" unmittelbar nach metadata.create_all() in CreateTable.py verschiebe, funktioniert alles einwandfrei und schön; Wenn ich dieses Modul anrufe, kann ich es nicht zum Laufen bringen. Ich habe versucht, die Engine an userDataImport zu übergeben und alternativ das Verbindungsobjekt an userDataImport zu übergeben, aber keiner dieser Versuche erwies sich als fruchtbar (in beiden Fällen wurde die Engine = ... und conn = ... entfernt). Wo gehe ich falsch?

Antwort

0

So fand ich eine interessante Lösung für dieses Problem. Das Problem war in der Tat ein Problembereich. Angesichts der Tatsache, dass ich keinen Kontext für users in der Einfügeoperation hatte, wurde Python verwirrt. So fand ich eine SQL-ähnliche Methode, die SQL-Anweisungen innerhalb einer an die Ausführungsfunktion übergebenen Zeichenfolge aufruft. Auf diese Weise behandelt SQLAlchemy das Parsen der SQL und verweist auf die Tabellen, da sie an eine Verbindung übergeben wurde, die als Kontext für users diente.Die Lösung sieht wie folgt aus:

engine = create_engine(r'<path to database') 
metadata = MetaData(engine) 
metadata.reflect() 

with engine.begin() as conn: 
    conn.execute("insert into users (userid, altid, lname, fname, phone_num, email_addr) values (<user id>, <alternate id>, <last name>, <first name>, <phone number>, <email address>)) 

dass in geschlossenen Einheiten in weniger als und Ur-als-Zeichen sind spezielle Werte. Das fügt erfolgreich Daten in der Datenbank wie gewünscht in der ursprünglichen Frage ein. Ebenso funktioniert update/select auch mit dieser SQL-ähnlichen Methode, während der Standard users.update(...)users.select(...) nicht funktioniert.

Für die Nachwelt ist hier die SQLAlchemy Dokumentationsseite, die für SQL-ähnliche Einfügung diese besondere Syntax enthält: http://docs.sqlalchemy.org/en/rel_1_0/core/tutorial.html#using-textual-sql

0

Ich bin mir nicht sicher, aber es scheint mir, dass Sie Benutzer von CreateTable importieren sollten. Etwas wie:

from .CreateTable import users 

wenn Create und import Dateien im selben Verzeichnis oder einem anderen Pfad wie from <some-directory>.CreateTable import users

Für weitere Informationen, die Sie in meinem einfachen Kolben-Projekt sehen: bitbucket-repository

+0

Ich glaube nicht, das ist schon die Lösung. Zunächst einmal funktioniert es nicht. Zweitens ging es darum, die Importanweisungen von den Create Table-Anweisungen zu abstrahieren, die diese Lösung völlig außer Acht lässt. Ich würde erwarten, dass eine Datenbank in der Lage wäre, Daten in ihre Tabellen importieren zu können, ohne jedes Mal auf das create table-Skript verweisen zu müssen. Das scheint einfach nicht richtig zu sein. –

0

Das Herz das Problem ist, dass Sie users in Ihrem importData.py definieren müssen. Was soll users sein? Nun, Sie haben eine Definition in einer anderen Datei (CreateTable.py), also sollten Sie sie wahrscheinlich importieren.

Aber Moment mal, das funktioniert nicht. Warum? Denn wenn Sie CreateTable importieren, versuchen Sie sofort, importData erneut zu importieren, so dass Sie mit einem Zirkelverweis enden.

Wie lösen Sie dieses Problem? Die Antwort ist die Tabellendefinitionen Faktor aus:

# db.py 
from sqlalchemy import * 

engine = create_engine(...) 
metadata = MetaData(engine) 

users = Table(...) 
subscribables = Table(...) 
... 

Dann können Sie db in Ihren Skripten importieren.

# CreateTable.py 
from db import metadata 
from importData import userDataImport 

if __name__ == "__main__": 
    metadata.drop_all() 
    metadata.create_all() 
    userDataImport() 

Und importData.py:

# importData.py 
from db import users 

def userDataImport(): 
    conn.execute(users.insert(), ...) 
+0

Metadaten sind eine Entität in SQLAlchemy selbst, die unabhängig von einem Python-Modul als Referenz auf die Datenbank selbst dienen soll. Metadaten sollten innerhalb jedes Moduls, das eine Verbindung zur Datenbank herstellt, erneut instanziiert werden. Siehe: http://docs.sqlalchemy.org/en/rel_1_0/core/metadata.html#metadata-scribing –

+0

@LukeMills Das ist offensichtlich falsch. Ich weiß nicht, woher du diese Idee hast; Die Dokumentation sagt das sicher nicht. – univerio

+0

In meiner Lektüre glaubte ich, dass Metadaten ein Objekt waren, das Informationen zu den Tabellen der Datenbank enthielt und somit der Datenbank zugeordnet war. Es ist nicht nur eine lokale Variable, wie Ihre Lösung vorschlägt. –

Verwandte Themen