【问题标题】:Connecting to IBM AS400 server for database operations hangs连接到 IBM AS400 服务器以进行数据库操作挂起
【发布时间】:2019-01-18 03:10:06
【问题描述】:

我正在尝试用 Python 与 AS400 交谈。目标是使用 SQLAlchemy,但当我无法让它工作时,我退回到一个更基本的脚本,只使用 ibm_db 而不是 ibm_db_sa。

import ibm_db
dbConnection = ibm_db.pconnect("DATABASE=myLibrary;HOSTNAME=1.2.3.4;PORT=8471;PROTOCOL=TCPIP;UID=username;PWD=password", "", "") #this line is where it hangs
print ibm_db.conn_errormsg()

问题似乎出在端口上。如果我使用在所有示例中看到的 50000,则会出现错误。如果我使用 446,我会收到错误消息。令人费解的是:如果我使用 8471,IBM says to do,我不会收到任何错误,没有超时,没有任何响应。我已经让脚本运行了二十多分钟,它就坐在那里,什么也不做。它处于活动状态,因为我根本无法使用命令提示符,但它从来没有给我任何形式的反馈。

我每天工作的公司都使用同样的 400,用于记录、发送电子邮件和(大量)数据库使用,所以我知道它有效。我们使用的软件在幕后与数据库对话,在我的机器上运行良好。这告诉我我的驱动程序很好,网络设置正确,等等。我什至可以从这里 telnet 到 400。

我在 SQLAlchemy 和 ibm_db 电子邮件列表中,并且已经就这个问题与他们沟通了几天。我也用谷歌搜索了很多,我开始在我的搜索结果中用完未访问的链接。似乎没有人有连接无限期挂起的问题。如果有什么我可以在 Python 中尝试的,我会尝试的。我不直接处理 400,但我可以要求负责检查/配置我需要的任何东西的人。正如我所说,几个工作站可以毫无问题地与 400 的数据库通信,并且如果从 400 本身运行查询,则针对我想要访问的库运行的查询工作正常。如果有人有任何建议,我将不胜感激。谢谢!

【问题讨论】:

  • 如果你在这方面取得了任何进展,如果你在这里分享它会很棒。我正在查看ibm_db_sa 的代码,看看是否有什么东西突然出现在我身上,并且发生了一些事情:pyodbc.py module within ibm_db_sa 有一个名为AS400Dialect_pyodbc 的类,它具有pyodbc_driver_name 的正确值。很明显,至少 一些 尝试让 SQLAlchemy 与 DB2 for i 一起工作。
  • 我没有。好吧,我的应用程序正在发展,但现在我只依赖 pyodbc。我尝试通过连接到 pyodbc 来使用 SA,然后将执行连接的函数传递给 create_engine,但这不起作用。
  • 没有 SQLAlchemy 的额外功能对您的伤害有多大?您(a)对 Python 的了解程度和(b)对 SQLAlchemy 的了解程度如何?我问的原因是因为通过更多的戳戳和刺激,我设法让create_engine() 成功创建了一个引擎,并使用该引擎进行裸 SQL 查询。换句话说,我可以让 SQLAlchemy 充当 PyODBC 的极其复杂的包装器,而没有任何附加值。我很高兴分享我的发现,但我从未使用过 ORM,因此在您充分利用 SQLAlchemy 之前,可能还存在更多问题。
  • 因此,您的知识来源是,如果需要进行更多的实验和修复,您可能不得不卷起袖子,弄脏手。
  • 我在 Python 中感觉很舒服,但我是 SQLAlchemy 的新手。我想使用SA的主要原因是ORM的方便,所以如果它只能处理直接的SQL,我想我还不如坚持使用pyodbc。不过,感谢您的跟进。

标签: python database ibm-midrange


【解决方案1】:

README for ibm_db_sa 仅在“支持的数据库”部分列出了 DB2 for Linux/Unix/Windows。所以它很可能不适用于 DB2 for i,至少不是开箱即用。

由于您已声明您拥有适用于 Windows 的 IBM System i Access,因此我强烈建议您仅使用其中一种驱动程序(如 @Charles 所述,ODBC、OLEDB 或 ADO.NET)。

就个人而言,我总是使用 ODBC,与 pyodbcpypyodbc 一起使用。任何一个都可以正常工作。一个简单的例子:

import pyodbc

connection = pyodbc.connect(
    driver='{iSeries Access ODBC Driver}',
    system='11.22.33.44',
    uid='username',
    pwd='password')
c1 = connection.cursor()

c1.execute('select * from qsys2.sysschemas')
for row in c1:
    print row

现在,SQLAlchemy 的连接方法之一是pyodbc,所以我认为如果你可以直接使用pyodbc 建立连接,你可以通过某种方式配置 SQLAlchemy 来做同样的事情。但我自己不是 SQLAlchemy 用户,所以我没有示例代码。

更新

我设法让 SQLAlchemy 连接到我们的 IBM i 并直接执行 SQL 查询。换句话说,让它获得与直接使用 PyODBC 大致相同的功能。 我还没有测试任何其他 SQLAlchemy 功能。 我在 Windows 7 机器上设置连接所做的工作:

  • ibm_db_sa 安装为 SQLAlchemy 方言
    您也许可以为此使用pip,但我使用的是低技术含量的方式:

    1. 从 PyPI 下载 ibm_db_sa
      在撰写本文时,最新版本为 0.3.2,于 2014-10-20 上传。可以想象,以后的版本要么被修复,要么以不同的方式被破坏(所以在未来,我要描述的修改可能是不必要的,或者它们可能不起作用)。
    2. 解压存档 (ibm_db_sa-0.3.2.tar.gz) 并将随附的 ibm_db_sa 目录复制到 sqlalchemy\dialects 目录中。
  • 修改sqlalchemy\dialects\ibm_db_sa\pyodbc.py

    • initialize() 方法添加到AS400Dialect_pyodbc
      这样做的重点是覆盖DB2Dialect 中的同名方法,AS400Dialect_pyodbc 继承自该方法。问题是DB2Dialect.initialize() 尝试设置属性dbms_verdbms_name,当使用 PyODBC 连接到 IBM i 时,这两个属性都不可用或相关(据我所知)。
    • 添加模块级名称dialect并将其设置为AS400Dialect_pyodbc

上述修改的代码应放在文件末尾,如下所示:

    def initialize(self, connection):
        super(DB2Dialect, self).initialize(connection)

dialect = AS400Dialect_pyodbc

注意缩进!记住,initialize() 方法需要属于 AS400Dialect_pyodbc 类,dialect 需要是模块的全局变量。

最后,您需要为引擎创建者提供正确的 URL:

'ibm_db_sa+pyodbc://username:password@host/*local'

(显然,将usernamepasswordhost 替换为有效值。)

就是这样。此时,您应该能够创建引擎,连接到 i,并通过 SQLAlchemy 执行普通 SQL。我认为很多 ORM 的东西在这一点上也应该可以工作,但我还没有验证这一点。

【讨论】:

  • 好吧,这似乎行得通!我可以运行查询,并且显然可以连接!关于将 ibm_db 用于这些东西的内容太多了,我很惊讶 pyodbc 在一分钟内完成了这项工作,而 ibm_db/ibm_db_sa 已经失败了好几天。现在我只需要弄清楚如何将它重新连接到 sqlalchemy 中。谢谢您的帮助。也感谢@Charles,感谢您在过去几天的所有回答。
  • 我遇到了同样的问题,但只能访问 linux 服务器。我假设 pyodbc 仅适用于 Windows 系统。你知道linux的解决方案吗?
  • @Jimmy - 也许你会发现一些有用的东西here
  • @JohnY 这绝对有帮助!
  • 您有将数据回写到 i 数据库的经验吗?到目前为止,我已经尝试了许多库、方言、驱动程序等的组合,但要么我无法建立连接,要么无法将内容写回数据库。使用上面的解决方案,我可以建立连接,但似乎无法创建新表。令人惊讶的是,我在执行 SQL 语句时没有收到任何错误。
【解决方案2】:

找出所需端口的方法是查看 IBM i 上的服务表条目。

您的 IBM i 人员可以使用 iNav GUI 或绿屏使用服务表条目 (WRKSRVTBLE) 命令

应该得到这样的屏幕:

Service                                  Port  Protocol  

as-admin-http                            2001  tcp       
as-admin-http                            2001  udp       
as-admin-https                           2010  tcp       
as-admin-https                           2010  udp       
as-central                               8470  tcp       
as-central-s                             9470  tcp       
as-database                              8471  tcp       
as-database-s                            9471  tcp  
drda                                      446  tcp
drda                                      446  udp     

数据库的默认端口确实是 8471。虽然 drda 用于“分布式数据库”操作。

基于此thread,要使用 ibm_db 连接到 IBM i 上的 DB2,您需要 IBM Connect 产品;这是一个必须付费的商业套餐。

thread 建议通过 pyodbc 模块使用 ODBC。它还表明通过 JT400 工具包的 JDBC 也可以工作。

【讨论】:

  • 感谢您的快速回复。我会要求他们仔细检查端口,但我被告知没有人修改过其中任何一个。如果我尝试 446 而不是 8471,我会得到类似“SQL 语句执行失败,因为通信数据流中的错误会影响后续命令和 SQL 语句的成功执行”。 SQLCode=-30020-0206, SQLState=58009
  • 我忘了说我已经安装了所有必要的 IBM 驱动程序和产品(我们公司可以访问这些)。事实上,我们使用的其他软件必须与我的机器上的 400 通信而没有问题,所以我很肯定我拥有所有必要的软件。此外,我刚刚确认我们的端口设置与标准端口一样(因此 446 和 8471 是两个可能的端口)。然而,8471 是挂起并且从不出错或超时的,而 446 在两秒内出错。
  • 补充一点查尔斯的回答,网上几乎所有的例子都是针对 DB2 LUW 或 DB2 for mainframe。您确实需要 DB2 for IBM i 的示例。此外,它不是 AS400,这在寻求帮助时非常重要——如果有人发布了 AS/400 的东西,它要么是古老的,要么是古老的,而且两者都不太可能有帮助。试试 IBM i 甚至 iSeries。
  • 我的老板和其他使用该系统的人都称它为 AS400,所以我认为这是实际名称。感谢您对此的澄清。另外,邮件列表告诉我只使用 446,而不是 8471。当我这样做时,我得到 SQLCode=-30020"0206")""。 SQL 状态 = 58009。嘿,至少尝试不再挂起!我确定我的用户名和密码正确,主机 IP 地址和协议设置 (TCP/IP) 也是正确的。不知道……IP地址前需要加“http://”吗?
  • 在我(承认有限)的理解中,Python 在使用 ibm_db 时需要 DB2 Connect(或其他类似的驱动程序)。这仅仅是因为它提供了一个非常标准的 DRDA 连接,例如,通过端口 446。如果您必须使用 DRDA,选项是有限的。但是通过 pyodbc 工作的 iAccess ODBC 驱动程序并没有建立相同的连接。它通过端口 8471 连接到数据库“主机服务器”,并具有单独的许可要求。我使用 pyodbc 来避免 DB2 Connect,就像他的回答中的 @JohnY 一样。
【解决方案3】:

这是一个使用 as400、sqlalchemy 和 pandas 的示例。 此示例采用一堆 csv 文件并使用 pandas/sqlalchemy 插入。 仅适用于 windows,在 linux 上 i 系列 odbc 驱动程序段错误(Centos 7 和 Debian 9 x68_64)

客户端是 Windows 10。

我的as400版本是7.3

Python 是 2.7.14

使用 pip 安装:pandas、pyodbc、imb_db_sa、sqlalchemy

你需要从ftp://public.dhe.ibm.com/as400/products/clientaccess/win32/v7r1m0/servicepack/si66062/为windows安装i access

另外,@JohnY 对 pyodbc.py 的修改 C:\Python27\Lib\site-packages\sqlalchemy\dialects\ibm_db_sa\pyodbc.py 将第 99 行更改为

    pyodbc_driver_name = "IBM i Access ODBC Driver"

odbc 驱动改名了。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
from sqlalchemy import create_engine
import glob

csvfiles=(glob.glob("c:/Users/nahum/Documents/OUT/*.csv"))
df_csvfiles = pd.DataFrame(csvfiles)
for index, row in df_csvfiles.iterrows():
    datastore2=pd.read_csv(str(row[0]), delimiter=',', header=[0],skipfooter=3)
    engine = create_engine('ibm_db_sa+pyodbc://DB2_USER:PASSWORD@IP_SERVER/*local')
    datastore2.to_sql('table', engine, schema='SCHEMA', chunksize=1000, if_exists='append', index=False)

希望对你有帮助。

【讨论】:

    【解决方案4】:

    如果您不需要 Pandas/SQLAlchemy,只需按照 John Y's answer 中的建议使用 pyodbc。否则,您可以尝试在下面做对我有用的事情。它取自我对my own, similar question 的回答,您可以查看更多关于不起作用工作的详细信息(在让它工作之前,我尝试了很多方法,但都失败了)。

    1. 我在我的项目中创建了一个空白文件来安抚我收到的这条消息:

      无法打开'hashtable_class_helper.pxi':找不到文件 (file:///c:/git/dashboards/pandas/_libs/hashtable_class_helper.pxi)。

      (我的项目文件夹是C:/Git/dashboards,所以我创建了路径的其余部分。)

    2. 有了该文件,下面的代码现在对我有用。作为记录,无论ibm_db_sa 模块是否按照John Y's answer 中的建议进行修改,它似乎都可以工作,所以我建议不要理会该模块。请注意,虽然它们不是直接导入的,但您需要安装这些模块:pyodbcibm_db_sa,可能还有future(如果使用 Python 2……我忘了是否有必要)。如果您使用的是 Python 3,我将需要 urllib.parse 而不是 urllib。我的电脑上还安装了 i Access 7.1 驱动程序,这可能会起作用。

    import urllib
    import pandas as pd
    from sqlalchemy import create_engine
    
    CONNECTION_STRING = (
        "driver={iSeries Access ODBC Driver};"
        "system=ip_address;"
        "database=database_name;"
        "uid=username;"
        "pwd=password;"
    )
    
    SQL= "SELECT..."
    
    quoted = urllib.quote_plus(CONNECTION_STRING)
    engine = create_engine('ibm_db_sa+pyodbc:///?odbc_connect={}'.format(quoted))
    
    df = pd.read_sql_query(
        SQL,
        engine,
        index_col='some column'
    )
    print df
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-25
      • 1970-01-01
      • 1970-01-01
      • 2012-03-22
      • 1970-01-01
      • 2017-08-29
      相关资源
      最近更新 更多