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

2024-05-10 05:23:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我正试着用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,我不会得到任何错误、超时和响应。我已经让剧本运行了20多分钟,它只是坐在那里,什么也没做。它是活动的,因为我根本不能使用命令提示符,但它从不给我任何反馈。

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

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


Tags: import脚本数据库目标dbsqlalchemy电子邮件错误
3条回答

找出需要哪个端口的方法是查看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     

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

基于这个thread,要使用ibm i上的ibm db连接到DB2,您需要ibm connect产品;这是一个必须付费的商业包。

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

下面是一个使用as400、sqlalchemy和pandas的示例。 这个例子需要一堆csv文件,并使用pandas/sqlalchemy插入。 仅适用于windows,在linux上i系列odbc驱动程序segfaults(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/安装i access for windows

另外,@JohnY在pyodbc.py上的修改 C: \Python27\Lib\site packages\sqlalchemy\diactals\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)

希望有帮助。

README for ^{}只在“支持的数据库”部分列出了用于Linux/Unix/Windows的DB2。所以它很可能不适用于我的DB2,至少不是现成的。

既然您已经声明您拥有IBM System i Access for Windows,我强烈建议您只使用它附带的一个驱动程序(ODBC、OLEDB或ADO.NET,正如@Charles所提到的)。

就我个人而言,我总是使用ODBC,使用^{}^{}。两种都可以。一个简单的例子:

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下载^{}
      截至本文撰写时,最新版本为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的东西也应该在这一点上起作用,但我还没有证实这一点。

相关问题 更多 >