将 pyodbc Connection 对象与 pandas 一起使用时收到警告

Jos*_*tel 76 sql-server pyodbc python-3.x pandas

我试图理解当我设置 python 代码在 VM 服务器上运行时开始出现的以下错误,该服务器在我的桌面上安装了 3.9.5 而不是 3.8.5。不确定这是否重要,但这可能是部分原因。

错误

C:\ProgramData\Miniconda3\lib\site-packages\pandas\io\sql.py:758: UserWarning: pandas only support SQLAlchemy connectable(engine/connection) or
database string URI or sqlite3 DBAPI2 connection
other DBAPI2 objects are not tested, please consider using SQLAlchemy
  warnings.warn(
Run Code Online (Sandbox Code Playgroud)

这是一个相当简单的 .py 文件,该文件导入 pyodbc 和 sqlalchemy fwiw。产生警告的 sql 调用的相当通用/简单的版本是:

myserver_string = "xxxxxxxxx,nnnn"
db_string = "xxxxxx"

cnxn = "Driver={ODBC Driver 17 for SQL Server};Server=tcp:"+myserver_string+";Database="+db_string +";TrustServerCertificate=no;Connection Timeout=600;Authentication=ActiveDirectoryIntegrated;"

def readAnyTable(tablename, date):
    conn = pyodbc.connect(cnxn)
    
    query_result = pd.read_sql_query(
            ''' 
                 SELECT *
                 FROM [{0}].[dbo].[{1}]
                where Asof >= '{2}'
            '''.format(db_string,tablename,date,), conn)
            
    conn.close()
    
    return query_result
Run Code Online (Sandbox Code Playgroud)

我在 python 中看到的使用 pyodbc 的所有示例看起来都非常相似。pyodbc 是否已被弃用?有没有更好的方法可以在没有警告的情况下达到类似的结果?

Gor*_*son 86

\n

pyodbc 是否已被弃用?

\n
\n

不。至少在过去的几年里,pandas 的文档已经明确指出它想要

\n
    \n
  1. 一个 SQLAlchemy Connectable(即EngineorConnection对象),
  2. \n
  3. 包含 SQLAlchemy 连接 URL 的字符串,或者
  4. \n
  5. SQLite DBAPI连接。
  6. \n
\n

(转向 SQLAlchemy 几乎是普遍的,但他们继续支持 SQLite 连接以实现向后兼容性。)人们一直在传递其他 DBAPI 连接(如 pyodbcConnection对象)进行读取操作,并且 pandas 没有抱怨 \xe2\x80\xa6到目前为止。

\n
\n

有没有更好的方法可以在没有警告的情况下达到类似的结果?

\n
\n

是的。您可以使用现有的 ODBC 连接字符串并使用它来创建 SQLAlchemy对象,如SQLAlchemy 1.4 文档Engine中所述:

\n
from sqlalchemy.engine import URL\nconnection_string = "DRIVER={ODBC Driver 17 for SQL Server};SERVER=dagger;DATABASE=test;UID=user;PWD=password"\nconnection_url = URL.create("mssql+pyodbc", query={"odbc_connect": connection_string})\n\nfrom sqlalchemy import create_engine\nengine = create_engine(connection_url)\n
Run Code Online (Sandbox Code Playgroud)\n

然后使用 SQLAlchemyengine来处理您需要的 pandas 方法。例如,使用 SQLAlchemy 2.0 和 pandas 1.5.3:

\n
import pandas as pd\nimport sqlalchemy as sa\n\n# \xe2\x80\xa6\n\nwith engine.begin() as conn:\n    df = pd.read_sql_query(sa.text("SELECT \'thing\' as txt"), conn)\n
Run Code Online (Sandbox Code Playgroud)\n

  • 知道为什么 pandas 团队选择不支持 DBAPI2 连接吗?鉴于 DBAPI2 的广泛使用,这似乎是一个奇怪的选择(我认为这是 Python 程序与数据库服务器通信的默认方式) (6认同)
  • 我有一个 postgresql 数据库;我正在使用 psycopg2.pool.ThreadedConnectionPool 并且 pandas 遇到了问题 (2认同)

Raf*_*ael 18

这个对我有用。注意,它将忽略所有当前和未来的警告。

import warnings

warnings.filterwarnings('ignore')
Run Code Online (Sandbox Code Playgroud)

  • 这是非常有趣的答案:d (8认同)
  • 通过额外的支持信息可以改进您的答案。请[编辑]添加更多详细信息,例如引文或文档,以便其他人可以确认您的答案是正确的。您可以[在帮助中心](/help/how-to-answer)找到有关如何写出好的答案的更多信息。 (4认同)
  • 我认为这里没有回答这个问题,而是压制警告,这并不能解决问题。链接此-> /sf/answers/4975841391/ (2认同)

Jon*_*out 7

    import pandas as pd
    import pyodbc
    import sqlalchemy as sa
    import urllib
    from sqlalchemy import create_engine, event
    from sqlalchemy.engine.url import URL
    
    server = 'IP ADDRESS or Server Name' 
    database = 'AdventureWorks2014' 
    username = 'xxx' 
    password = 'xxx' 
    
    params = urllib.parse.quote_plus("DRIVER={SQL Server};"
                                     "SERVER="+server+";"
                                     "DATABASE="+database+";"
                                     "UID="+username+";"
                                     "PWD="+password+";")
    
    engine = sa.create_engine("mssql+pyodbc:///?odbc_connect={}".format(params))
    
    qry = "SELECT t.[group] as [Region],t.name as [Territory],C.[AccountNumber]"
    qry = qry + "FROM [Sales].[Customer] C INNER JOIN [Sales].SalesTerritory t on t.TerritoryID = c.TerritoryID "
    qry = qry + "where StoreID is not null and PersonID is not null"

with engine.connect() as con:
    rs = con.execute(qry)

    for row in rs:
        print (row)
Run Code Online (Sandbox Code Playgroud)

您可以使用 SQL Server 名称或 IP 地址,但这需要基本的 DNS 列表。不过,大多数企业服务器应该已经有此列表。您可以使用nslookup命令提示符中的命令后跟服务器名称或 IP 地址来检查服务器名称或 IP 地址。

我在 VMWare 上运行的 Ubuntu 服务器上使用 SQL 2017。我在这里连接 IP 地址,作为更广泛的“在 Ubuntu 上运行 MSSQL”项目的一部分。

如果您使用 Windows 凭据进行连接,则可以将 params 替换为 参数trusted_connection

params = urllib.parse.quote_plus("DRIVER={SQL Server};"
                                 "SERVER="+server+";"
                                 "DATABASE="+database+";"
                                 "trusted_connection=yes")
Run Code Online (Sandbox Code Playgroud)


小智 6

由于它是一个警告,我使用警告 python 库抑制了该消息。希望这可以帮助

import warnings
with warnings.catch_warnings(record=True):
    warnings.simplefilter("always")
    #your code goes here
Run Code Online (Sandbox Code Playgroud)