2009-07-26 19 views
3

私はPythonとftplibを使って、z/os PDSからいくつかのテキストファイルのダウンロードを自動化しようとしています。Pythonとftplib.FTPでテキストファイルをダウンロードする

ホストファイルはEBCDICなので、単にFTP.retrbinary()を使うことはできません。

FTP.retrlines()は、open(file、w).writelinesをコールバックとして使用してももちろんEOLを提供しません。

私はこのコードを "私には間違いない"と思いついたのですが、私が相対的なPythonのnoobであるので、誰かがより良いアプローチを提案できますか?明らかに、この質問を単純にするために、これは最終的な鐘と笛のことではありません。

多くのありがとうございます。

#!python.exe 
from ftplib import FTP 

class xfile (file): 
    def writelineswitheol(self, sequence): 
     for s in sequence: 
      self.write(s+"\r\n") 

sess = FTP("zos.server.to.be", "myid", "mypassword") 
sess.sendcmd("site sbd=(IBM-1047,ISO8859-1)") 
sess.cwd("'FOO.BAR.PDS'") 
a = sess.nlst("RTB*") 
for i in a: 
    sess.retrlines("RETR "+i, xfile(i, 'w').writelineswitheol) 
sess.quit() 

アップデート:Python 3.0プラットフォームは、Windows XPではMingWです。

z/os PDSは、レコード区切り文字として行末に頼るのではなく、固定レコード構造を持っています。ただし、z/os FTPサーバーは、テキストモードで送信するとき、retrlines()が取り除かれたレコードの終了を提供します。アップデートを閉じる

ここで継続的な発展の基礎になります私の改訂ソリューション、(例えば、組み込みのパスワードを削除する)です:

import ftplib 
import os 
from sys import exc_info 

sess = ftplib.FTP("undisclosed.server.com", "userid", "password") 
sess.sendcmd("site sbd=(IBM-1047,ISO8859-1)") 
for dir in ["ASM", "ASML", "ASMM", "C", "CPP", "DLLA", "DLLC", "DLMC", "GEN", "HDR", "MAC"]: 
    sess.cwd("'ZLTALM.PREP.%s'" % dir) 
    try: 
     filelist = sess.nlst() 
    except ftplib.error_perm as x: 
     if (x.args[0][:3] != '550'): 
      raise 
    else: 
     try: 
      os.mkdir(dir) 
     except: 
      continue 
     for hostfile in filelist: 
      lines = [] 
      sess.retrlines("RETR "+hostfile, lines.append) 
      pcfile = open("%s/%s"% (dir,hostfile), 'w') 
      for line in lines: 
       pcfile.write(line+"\n") 
      pcfile.close() 
     print ("Done: " + dir) 
sess.quit() 

はジョンの両方に感謝し、 Vinay

+0

質問を編集してPDSファイルを記述してください。 「一部のテキストファイル」はむしろ不適切です。 –

+0

また、どのプラットフォーム、どのバージョンのPython、なぜあなたのwritelineswitheolメソッドが '\ n'の代わりに '\ r \ n'を追加するのかを記述してください。実際にこれを実行して出力を調べて、プラットフォームに適切な回線終端があることを確認してください。 –

+0

完了。私はcorp.firewallの外で自宅でいくつかの週末のコーディングをしているので、私は今週の後半にそのアイデアをテストしています。 –

答えて

3

私がz/OSから再帰的にデータセットをダウンロードする方法を見つけようとしていたときに、この質問に直面しました。私は今、メインフレームからebcdicファイルをダウンロードするために、何年もの間、単純なPythonスクリプトを使用してきました。これは効果的です:

def writeline(line): 
    file.write(line + "\n") 

file = open(filename, "w") 
ftp.retrlines("retr " + filename, writeline) 
3

ファイルをバイナリ形式(retrbinaryを使用)でダウンロードし、codecsモジュールを使用してEBCDICからどのような出力エンコード欲しいです。 z/OSシステムで使用されている特定のEBCDICコード・ページ(たとえば、cp500)を知っておく必要があります。あなたがラインとあなたのラインが後ろに来ている取得するためにretrlinesを使用する必要がある場合:

file = open(ebcdic_filename, "rb") 
data = file.read() 
converted = data.decode("cp500").encode("utf8") 
file = open(utf8_filename, "wb") 
file.write(converted) 
file.close() 

更新:ファイルが小さい場合、あなたも(UTF-8への変換のため)のような何かを行うことができますコールバックが各行に対して1回呼び出されるため、正しいエンコーディングでは、あなたのアプローチは機能しません。したがって、コールバックではsequenceが行になり、forループは行内の個々の文字を出力に出力しますはそれぞれ独自の行になります。したがって、forループではなくself.write(sequence + "\r\n")を実行したいと思うかもしれません。それでも、fileをサブクラス化するだけでは、このユーティリティメソッドを追加することはできません。おそらく、bells-and-whistlesバージョンの別のクラスにある必要があります。

+0

ありがとう、Vinay、これは興味深い考えですが、改行を挿入するにはどうすればいいですか? (これらはOpenEditionファイルではなく、従来のzos PDSです) –

+0

EBCDIC改行ではなく、ホストシステム上でどのように行が終了していますか? –

+1

ホストファイルシステムはレコードベースです。これは固定長です。この場合、すべてのレコードの長さは同じですが、可変長で、長さは各レコードの先頭の記述子フィールドに格納されます。 FTP.retrlines()はレコードを正しく抽出しますが、(正しく、私は思うが)改行を提供しません。 –

1

writelineswitheolメソッドは、 '\ n'の代わりに '\ r \ n'を追加し、その結果をテキストモードで開いたファイルに書き込みます。あなたが実行しているプラ​​ットフォームに関係なく、効果は望ましくない '\ r'になります。 '\ n'を追加するだけで、適切な行末が得られます。

適切なエラー処理を "鐘と笛"のバージョンにするべきではありません。ファイルopen()がtry/exceptにあり、出力ファイルハンドルへの参照を保持し、書き込み呼び出しがtry/exceptにあり、callback_obj.close()メソッドがあるようにコールバックを設定する必要があります。 retrlines()が明示的にfile_handle.close()(try/exceptで)に戻るときに使用します。そうすれば、エラー処理の説明が得られます。あなたのファイルが暗黙的にクローズされるときと、ファイルハンドルが足りなくなる危険性について考える必要はありません。

Python 3.x ftplib.FTP.retrlines()は、有効なUnicode文字列であるstrオブジェクトを提供する必要があります。デフォルトのエンコーディングがlatin1ではない場合を除き、それらをエンコードする必要がありますWindowsのボックスには珍しい。期待されるEBCDICコードページで有効なすべての可能な256バイト(2)すべてのバイトで(1)テストファイルを持つ必要があります。

[少数の "衛生" 発言]

  1. あなたは3.0( "概念実証の" リリース)から3.1へのあなたのPythonのアップグレードを検討すべきです。あなたのコードのより良い理解を容易にするために

  2. 、あなたがirredeemably

  3. 二:-) 3つの以上の数十年前にFORTRANからの習慣を取得した「私」だけシーケンスインデックスとして、識別子として、また場合にのみ使用しますこれまでに発見された問題(行終端文字を各文字に追加する、間違った行終端文字)は、初めてテストしたときに表示されます。

+0

ジョン、ありがとう。私はあなたのただの批判を乗り越えていることを確信してください。 –

関連する問題