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:名称''未定义的主要内容,如果未能解决你的问题,请参考以下文章

NameError:名称'python'未定义[关闭]

Python - NameError:名称 itemgetter 未定义

Python 3:NameError:未定义名称“sklearn”

python怎么安装,怎么一直显示nameerror?

NameError:名称“reduce”未在 Python 中定义

NameError:未定义全局名称“PermissionError”(python 2.x)