web-dev-qa-db-ja.com

データベース操作のためにIBMAS400サーバーに接続するとハングする

PythonでAS400と通信しようとしています。目標はSQLAlchemyを使用することですが、それを機能させることができなかったときは、ibm_db_saの代わりにibm_dbだけを使用してより基本的なスクリプトに戻りました。

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がそうするように言っています 、エラー、タイムアウト、応答はまったくありません。スクリプトを20分以上実行したままにしましたが、スクリプトはそのままで何もしません。コマンドPromptをまったく使用できないため、アクティブですが、いかなる種類のフィードバックも提供されません。

これと同じ400は、私が毎日働いている会社で、ロギング、電子メール、および(大量の)データベースの使用に使用されているので、機能することはわかっています。私たちが使用しているソフトウェアは、バックグラウンドでデータベースと通信しますが、私のマシンでは問題なく動作します。これは、私のドライバーが優れていること、ネットワーク設定が正しいことなどを示しています。ここから400にtelnetで接続することもできます。

私はSQLAlchemyとibm_dbのメーリングリストに参加しており、この問題について何日も連絡を取り合っています。私はまたそれをグーグルで検索したので、検索結果の未訪問のリンクが不足し始めています。接続が無期限にハングするという問題を抱えている人はいないようです。 Pythonで試すことができるものがあれば、試してみます。私は400を直接扱っていませんが、必要なものは何でもチェック/構成するように依頼することができます。ただし、前述したように、複数のワークステーションは問題なく400のデータベースと通信でき、アクセスしたいライブラリに対してクエリを実行すると、400自体から実行した場合でも正常に機能します。何か提案があれば、聞いていただければ幸いです。ありがとう!

10
AH16

README for _ibm_db_sa_ は、「サポートされているデータベース」セクションにLinux/Unix/Windows用のDB2のみをリストしています。したがって、DB2 for iでは機能しない可能性が高く、少なくとも箱から出してすぐには機能しません。

IBM System i Access for Windowsを使用しているとおっしゃっていたので、付属のドライバーの1つ(@Charlesが述べたように、ODBC、OLEDB、またはADO.NET)を使用することを強くお勧めします。

個人的には、私は常にODBCを使用し、 pyodbc または 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の接続方法の1つはpyodbcなので、pyodbcを直接使用して接続を確立できれば、SQLAlchemyを同じように構成できると思います。しかし、私自身はSQLAlchemyユーザーではないので、そのためのサンプルコードはありません。

[〜#〜]更新[〜#〜]

SQLAlchemyをIBMiに接続して、直接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_ver_と_dbms_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'

(明らかに、usernamepassword、およびHostの代わりに有効な値を使用してください。)

それでおしまい。この時点で、エンジンを作成し、iに接続し、SQLAlchemyを介してプレーンSQLを実行できるはずです。この時点で多くのORMも機能するはずだと思いますが、これは検証していません。

11
John Y

これは、as400、sqlalchemy、およびpandasで動​​作する例です。この例では、多数のcsvファイルを取得し、pandas/sqlalchemyで挿入します。 Windowsでのみ機能し、Linuxではiシリーズのodbcドライバーのセグメンテーション違反(Centos7およびDebian9 x68_64)

クライアントはWindows10です。

私のas400バージョンは7.3です

Pythonは2.7.14です

pipでインストール:pandas、pyodbc、imb_db_sa、sqlalchemy

Windows用のiaccessをインストールする必要があります ftp://public.dhe.ibm.com/as400/products/clientaccess/win32/v7r1m0/servicepack/si66062/

さらに、pyodbc.py C:\ Python27\Lib\site-packages\sqlalchemy \方言\ ibm_db_sa\pyodbc.pyの@JohnYによる変更

    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)

それが役に立てば幸い。

1
ncastrog

必要なポートを見つける方法は、IBMiのサービステーブルエントリを調べることです。

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_dbを使用してIBM i上のDB2に接続するには、IBMConnect製品が必要です。これは、支払いが必要な商用パッケージです。

この スレッド は、pyodbcモジュールを介してODBCを使用することを示唆しています。また、JT400ツールキットを介したJDBCも機能する可能性があることを示唆しています。

1
Charles

Pandas/SQLAlchemyが必要ない場合は、 John Yの回答 で提案されているようにpyodbcを使用してください。それ以外の場合は、以下で私のために働いたことをやってみることができます。 私自身の同様の質問 に対する私の答えから取られています。これは、がしないことの詳細を確認できます。動作します(動作させる前に、さまざまな方法で試して失敗しました)。

  1. 受け取ったこのメッセージを和らげるために、プロジェクトに空のファイルを作成しました。

    'hashtable_class_helper.pxi'を開くことができません:ファイルが見つかりません(file:///c:/git/dashboards/pandas/_libs/hashtable_class_helper.pxi)。

    (私のプロジェクトフォルダーはC:/Git/dashboardsなので、残りのパスを作成しました。)

  2. そのファイルが存在するので、以下のコードが機能します。ちなみに、ibm_db_saモジュールが John Yの回答 で提案されているように変更されているかどうかに関係なく機能するようですので、そのモジュールはそのままにしておくことをお勧めします。直接インポートされませんが、次のモジュールをインストールする必要があることに注意してください:pyodbcibm_db_sa、場合によってはfuture(Python = 2 ...必要かどうか忘れます)Python 3を使用している場合は、urllibの代わりにurllib.parseが必要です。 iコンピューターにインストールされている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
0
MarredCheese