连接到 IBM AS400 服务器进行数据库操作挂起

Connecting to IBM AS400 server for database operations hangs

我正在尝试与 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,则会出现错误。令人困惑的部分是:如果我使用 IBM says to do 的 8471,我没有得到任何错误、没有超时、没有任何响应。我已经离开脚本 运行ning 二十多分钟了,它只是坐在那里,什么都不做。它处于活动状态,因为我根本无法使用命令提示符,但它从不给我任何类型的反馈。

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

我在 SQLAlchemy 和 ibm_db 电子邮件列表中,并且已经就此问题与他们沟通了好几天。我也用谷歌搜索了很多,以至于我开始 运行 从我的搜索结果中未访问过的链接中剔除。似乎没有人遇到连接无限期挂起的问题。如果Python有什么我可以尝试的,我会尝试的。我不直接与 400 打交道,但我可以向 check/configure 的人询问我需要的任何事情。正如我所说,多个工作站可以毫无问题地与 400 的数据库对话,并且如果来自 400 本身的 运行,则对我想访问的库的查询 运行 工作正常。如果有人有任何建议,我将不胜感激。谢谢!

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

您的 IBM i 人员可以使用 iNav GUI 或绿屏使用服务 Table 输入 (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     

DB 的默认端口确实是 8471。虽然 drda 用于 "distributed db" 操作。

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

thread 建议通过 pyodbc 模块使用 ODBC。它还表明通过 JT400 工具包 JDBC 也可能有效。

README for ibm_db_sa 仅列出 "Supported Database" 部分中 Linux/Unix/Windows 的 DB2。所以它很可能不适用于 DB2 for i,至少不是开箱即用。

既然你已经声明你有 Windows 的 IBM System i Access,我强烈建议只使用它附带的驱动程序之一(ODBC、OLEDB 或 ADO.NET,因为 @提到查尔斯)。

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

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 建立连接,您可以通过某种方式配置 SQL炼金术也一样。但我自己不是 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_pyodbcclass
      这样做的目的是覆盖 DB2Dialect 中的同名方法,AS400Dialect_pyodbc 继承自该方法。问题是 DB2Dialect.initialize() 尝试设置属性 dbms_verdbms_name,这两个属性在使用 PyODBC 连接到 IBM i 时都不可用或相关(据我所知)。
    • 添加模块级名称dialect并将其设置为AS400Dialect_pyodbcclass

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

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

dialect = AS400Dialect_pyodbc

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

最后,需要给引擎创建者权限URL:

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

(显然,用有效值代替 usernamepasswordhost。)

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

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

客户是Windows10.

我的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 的访问权限

此外@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)

希望对您有所帮助。

如果您不需要 Pandas/SQLAlchemy,只需按照 . Otherwise, you can try doing what worked for me, below. It's taken from my answer to 中的建议使用 pyodbc,您可以查看 不需要[=38] 的更多详细信息=] 工作(在让它工作之前,我尝试了很多方法但都失败了)。

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

    Unable to open 'hashtable_class_helper.pxi': File not found (file:///c:/git/dashboards/pandas/_libs/hashtable_class_helper.pxi).

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

  2. 有了那个文件,下面的代码现在对我有用了。作为记录,无论 ibm_db_sa 模块是否按照 中的建议进行修改,它似乎都有效,因此我建议单独保留该模块。请注意,虽然它们不是直接导入的,但您需要安装这些模块: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