Python / Access NameError:名称''未定义
Posted
技术标签:
【中文标题】Python / Access NameError:名称\'\'未定义【英文标题】:Python / Access NameError: name '' is not definedPython / Access NameError:名称''未定义 【发布时间】:2021-01-21 15:46:00 【问题描述】:我正在尝试将一些旧的 Access VBA 代码重写为 Python,但我遇到了以下错误: NameError: name 'ERTZ6635' is not defined
旧 VBA 代码
Set ConsTable = DB.OpenRecordset("SELECT * FROM table1")
ConsCount = 87404
If ConsCount > 0 Then
ConsTable.MoveFirst
For I = 1 To ConsCount
Set ConsBlendTable = DB.OpenRecordset("SELECT * FROM table2 WHERE CONS_BATCH = " & Char34(ConsTable!Batch))
Python 代码:
导入 win32com.client
dbe = win32com.client.Dispatch("DAO.DBEngine.120")
db = dbe.OpenDatabase(r"C:\Users\xyz\Desktop\acess.accdb")
ConsTable = db.OpenRecordset("select * from table1")
ConsCount = 87404
if ConsCount>0:
ConsTable.MoveFirst()
for i in range(1, ConsCount):
ConsBlendTable = db.OpenRecordset("SELECT * FROM table2 WHERE CONS_BATCH = " & eval(ConsTable.Fields["Batch"].Value))
而ERTZ6635的值就是ConsTable.Fields["Batch"].Value
中的值【问题讨论】:
你不应该在这里(或根本不)使用 eval 通过将eval
传递给ConsTable.Fields["Batch"].Value
,您将is 视为一个变量,而事实并非如此。
没有 eval 我有以下错误:TypeError: unsupported operand type(s) for &: 'str' and 'str'
VBA 中没有Char34()
。这可能是用户定义的方法。请在旧 VBA 中显示其定义。
【参考方案1】:
在 VBA 代码中,Char34()
可能是用户定义的函数,因为它不是 VBA 内置方法。然而,对于双引号,ASCII 表中的第 34 个字符有一个常量 Chr34
。因此,顾名思义,此方法可能会在输入参数值周围加上双引号。这很重要,因为您尝试使用eval
在 Python 中进行翻译。
所以简单的答案是包含双引号,您可以在 Python 中插入 F 字符串。
sql = f"""SELECT * FROM table2
WHERE CONS_BATCH = "ConsTable.Fields["Batch"].Value"
"""
ConsBlendTable = db.OpenRecordset(sql)
但是,在包括 VBA 和 Python 在内的任何语言中,不建议将参数字符串插值到 SQL 查询中。除了安全和效率问题之外,如果 value 本身包含双引号,此代码仍然会中断。
请考虑通过QueryDefs 在 MS Access SQL 引擎中支持的参数化。
VBA (根据之前的 SQL 连接调整)
Dim qdef As QueryDef
...
Set ConsTable = DB.OpenRecordset("SELECT * FROM table1")
' PREPARED STATEMENT (NO DATA)
sql = "PARAMETERS batch_prm TEXT(255);" _
& "SELECT * FROM table2 WHERE CONS_BATCH = batch_prm"
ConsTable.MoveFirst
Do While Not ConsTable.EOF
Set qdef = DB.CreateQueryDef("", sql)
qdef!batchprm = ConsTable!Batch ' BIND PARAMETER
Set ConsBlendTable = qdef.OpenRecordset() ' OPEN RECORDSET VIA QUERYDEF
...
ConsBlendTable.Close
ConsTable.MoveNext
Loop
ConsTable.Close
'RELEASE RESOURCES
Set ConsBlendTable = Nothing: Set ConsTable = Nothing
Set qdef = Nothing: Set DB = Nothing
Python (使用 try/except
进行正确的 COM 处理)
因此,在 Python 中,我们与 QueryDef
对象进行了类似的交互。下面使用传统的 DAO 循环遍历记录集中的每条记录(即,Do While Not rst.EOF
的翻译)。
import win32com.client
try:
dbe = win32com.client.Dispatch("DAO.DBEngine.120")
db = dbe.OpenDatabase(r"C:\Users\xyz\Desktop\acess.accdb")
ConsTable = db.OpenRecordset("SELECT * FROM table1")
# PREPARED STATEMENT
sql = """PARAMETERS batch_prm TEXT(255);
SELECT * FROM table2 WHERE CONS_BATCH = batch_prm
"""
ConsTable.MoveFirst()
while ConsTable.EOF == False:
qdef = db.CreateQueryDef("", sql)
# BIND PARAMETER
qdef.Parameters["batch_prm"].Value = ConsTable.Fields["Batch"].Value
# OPEN RECORDSET VIA QUERYDEF
ConsBlendTable = qdef.OpenRecordset()
...
ConsBlendTable.Close()
ConsTable.MoveNext()
ConsTable.Close()
except Exception as e:
print(e)
finally:
# RELEASE RESOURCES
ConsBlendTable = None; ConsTable = None
qdef = None; db = None; dbe = None
del ConsBlendTable; del ConsTable; del qdef; del db; del dbe
最后,我必须指出。不用直接翻译 VBA,而是使用 Python 的 DB-API,因为它可以在没有 DAO 或 COM 对象的情况下直接查询 MS Access 数据库,特别是维护良好的:pyodbc
。并使用JOIN
运行,而不是通过WHERE
进行迭代循环。是的,pyodbc
支持 parameters 和 ?
qmarks。
import pyodbc
dbname = r"C:\Users\xyz\Desktop\acess.accdb"
constr = f"DRIVER=Microsoft Access Driver (*.mdb, *.accdb);DBQ=dbname;"
conn = pyodbc.connect(constr)
cur = conn.cursor()
sql = """SELECT t1.Batch, t2.CONS_BATCH, ...
FROM table1 t1
INNER JOIN tbale2 t2
ON t1.Batch = t2.CONS_BATCH
"""
cur.execute(sql)
for row in cur.fetchall():
...
cur.close()
conn.close()
【讨论】:
以上是关于Python / Access NameError:名称''未定义的主要内容,如果未能解决你的问题,请参考以下文章
Python - NameError:名称 itemgetter 未定义
Python 3:NameError:未定义名称“sklearn”