2016-03-21 23 views
1

時,當試圖從一個JSON文件到使用SQLAlchemy的表達式語言數據庫導入用戶數據SQLAlchemy中,我得到的錯誤: NameError: name 'users' is not defined「NameError:名字‘<tableName>’沒有定義」導入數據

的回溯如下:

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 

我發出的Python程序的創建表的語句,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() 

然後我嘗試使用一個模塊導入數據,userDataImport的importData.py文件,其中包含以下範圍內:

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() 

但是SQLAlchemy中無法識別的用戶,這是我在CreateTable.py已經創建的表如果我在CreateTable.py中的metadata.create_all()之後立即從userDataImport模塊移動代碼,則一切正常並且很棒;在我稱之爲模塊的情況下,我無法使其工作。 我試圖將引擎傳遞給userDataImport,或者將連接對象傳遞給userDataImport,但這兩種嘗試都未見成效(在兩種情況下引擎= ...和conn = ...在哪裏被刪除)。我哪裏錯了?

回答

0

所以,我發現了一個有趣的解決這個問題。問題確實是一個範圍問題。鑑於我在插入操作中沒有users的上下文,Python變得困惑。所以我找到了一個更類似於SQL的方法來調用傳遞給execute函數的字符串中的SQL語句。這種方式SQLAlchemy處理了SQL的解析,並且引用了這些表,因爲它已傳遞給一個連接,該連接充當users的上下文。解決方案如下所示:

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>)) 

其中圍繞小於號和大於號的實體是特定值。 這成功地將數據插入到原始問題中發佈的所需方法中的數據庫中。同樣,更新/選擇也適用於這種類似於SQL的方法,而標準的users.update(...)users.select(...)沒有。

對於後人,這裏是其中包含了類似於SQL的插入這個特殊的語法SQLAlchemy的文檔頁面:http://docs.sqlalchemy.org/en/rel_1_0/core/tutorial.html#using-textual-sql

0

我不確定,但在我看來,您應該從CreateTable導入用戶。 喜歡的東西:

from .CreateTable import users 

,如果在同一個目錄,或其他的路徑類似from <some-directory>.CreateTable import users

欲瞭解更多信息,你可以看到在我的簡單的燒瓶項目CREATETABLE和IMPORTDATA文件:bitbucket-repository

+0

我不相信那是相當的解決方案。首先,它不起作用。其次,關鍵在於將創建表語句中的導入語句抽象出來,而這種解決方案完全忽視了這一點。我希望數據庫能夠讓我將數據導入到表中,而不必每次都引用create table腳本。這看起來不正確。 –

0

的心臟的問題是你需要在你的importData.py中定義users。什麼是users應該是?那麼,你有一個不同的文件中的定義(CreateTable.py),所以你可能應該導入它。

但是,掛了,這是行不通的。爲什麼?因爲當您導入CreateTable時,您立即嘗試再次導入importData,因此您最終得到了循環引用。

你如何解決這個問題?答案是分解出表的定義:

# db.py 
from sqlalchemy import * 

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

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

然後你就可以導入db在腳本中。

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

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

而且importData.py

# importData.py 
from db import users 

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

元數據是SQLAlchemy本身內的一個實體,應該作爲數據庫本身的引用,獨立於任何python模塊。應在每個建立到數據庫的連接的模塊中重新實例化元數據。請參閱:http://docs.sqlalchemy.org/en/rel_1_0/core/metadata.html#metadata-describing –

+0

@LukeMills這顯然是錯誤的。我不知道你從哪裏得到這個想法。該文件當然不會這麼說。 – univerio

+0

在我的閱讀中,我認爲元數據是一個包含與數據庫表有關的信息的對象,因此與數據庫相關聯。根據您的解決方案,這不僅僅是一個局部變量。 –

相關問題