&#34; NameError:name&#39; <tablename>&#39;没有定义&#34;在导入数据时在SQLAlchemy中

时间:2016-03-21 20:01:24

标签: python database sqlalchemy relational-database

尝试使用SQLAlchemy表达式语言将用户数据从JSON文件导入数据库时​​,出现错误: Sub updatedbtest2() Dim cn As ADODB.Connection, rs As ADODB.Recordset Dim rng As Range Dim lngRow As Long Dim sQID, LR Dim sSQL As String LR = Range("A" & Rows.Count).End(xlUp).Row 'Debug.Print LR 'Upd = LR - 1 lngRow = 2 Set cn = New ADODB.Connection cn.Open "Provider = Microsoft.ACE.OLEDB.12.0;" & _ "Data Source=C:\Database\sales.accdb;" Do While lngRow <= LR sQID = Cells(lngRow, 61).Value Set rs = New ADODB.Recordset sSQL = "SELECT * FROM PandR WHERE QID ='" & sQID & "';" With rs .Open Source:=sSQL, ActiveConnection:=cn, LockType:=adLockOptimistic .Fields("QorB") = Cells(lngRow, 60).Value .Fields("BDate") = Cells(lngRow, 62).Value .Update End With 'Next rng lngRow = lngRow + 1 rs.Close Set rs = Nothing Loop cn.Close Set cn = Nothing End Sub

回溯如下:

NameError: name 'users' is not defined

我在Python程序CreateTable.py:

中发出create table语句
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

然后我尝试使用importData.py文件中的模块userDataImport导入数据,该文件包含以下内容:

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

然而SQLAlchemy无法识别用户,这是我在CreateTable.py中创建的表。如果我在CreateTable.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() 之后立即从userDataImport模块移动代码,一切正常,花花公子;在我称这个模块无法让它工作的情况下。 我试图将引擎传递给userDataImport,并将连接对象传递给userDataImport,但这两种尝试都没有成效(在两种情况下引擎= ...和conn = ...删除)。我哪里错了?

3 个答案:

答案 0 :(得分:1)

所以我找到了解决这个问题的有趣方法。这个问题确实是一个范围问题。鉴于我在插入操作中没有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(...)则没有。

对于后代,这里是SQLAlchemy文档页面,其中包含类似SQL的插入的特定语法:http://docs.sqlalchemy.org/en/rel_1_0/core/tutorial.html#using-textual-sql

答案 1 :(得分:0)

我不确定,但在我看来,您应该从CreateTable导入用户。 类似的东西:

from .CreateTable import users

如果CreateTable和importData文件位于同一目录或其他路径中,如from <some-directory>.CreateTable import users

有关详细信息,您可以查看我的简单烧瓶项目:bitbucket-repository

答案 2 :(得分:0)

问题的核心是您需要在users中定义importData.py。什么是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(), ...)