문제

Python 및 FTPlib을 사용하여 AZ/OS PDS에서 일부 텍스트 파일을 자동화하려고합니다.

호스트 파일은 EBCDIC이므로 Ftp.retrbinary ()를 단순히 사용할 수는 없습니다.

ftp.retrlines (), Open (file, w) .writelines와 함께 사용하면 콜백으로 사용되면 물론 EOL을 제공하지 않습니다.

그래서 우선, 나는 "나에게 괜찮아 보이는이 코드를 생각해 냈지만, 상대적인 파이썬 멍청이이기 때문에 누구나 더 나은 접근법을 제안 할 수 있습니까? 분명히,이 질문을 단순하게 유지하기 위해, 이것은 마지막이 아닙니다.

많은 감사합니다.

#!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 서버는 레코드 엔딩을 제공합니다.

마감 업데이트 :

다음은 진행중인 개발의 기초가 될 수정 된 솔루션입니다 (예 : 내장 비밀번호 제거).

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()

John과 Vinay에게 감사드립니다

도움이 되었습니까?

해결책

Z/OS에서 데이터 세트를 재귀 적으로 다운로드하는 방법을 알아 내려고 노력 하면서이 질문을 발견했습니다. 메인 프레임에서 EBCDIC 파일을 다운로드하기 위해 몇 년 동안 간단한 파이썬 스크립트를 사용해 왔습니다. 효과적으로 다음을 수행합니다.

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

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

다른 팁

파일을 이진으로 다운로드 할 수 있어야합니다 (사용 retrbinary) 그리고 사용하십시오 codecs EBCDIC에서 원하는 출력 인코딩으로 변환하는 모듈. Z/OS 시스템 (예 : CP500)에서 사용되는 특정 EBCDIC 코드 페이지를 알아야합니다. 파일이 작 으면 (UTF-8로 변환하기 위해)와 같은 작업을 수행 할 수도 있습니다.

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

업데이트: 사용해야하는 경우 retrlines 라인을 얻고 라인이 올바른 인코딩으로 돌아 오려면 콜백이 각 라인마다 한 번 호출되므로 접근 방식이 작동하지 않습니다. 그래서 콜백에서 sequence 라인이 될 것이고, 당신의 루프는 라인에 출력에 개별 문자를 쓸 것입니다. 각각 자체 라인. 그래서 당신은 아마하고 싶을 것입니다 self.write(sequence + "\r\n") 대신 for 고리. 여전히 서브 클래스에 특히 옳다고 느끼지 않습니다 file 그러나이 유틸리티 방법을 추가하려면 아마도 다른 클래스에 있어야합니다. bells-and-whistles 버전.

WriteLineswitheol 메소드는 ' n'대신 ' r n'을 추가 한 다음 텍스트 모드에서 열린 파일에 결과를 씁니다. 어떤 플랫폼을 실행하든, 효과는 원치 않는 ' r'입니다. ' n'을 추가하면 적절한 라인 결말을 얻을 수 있습니다.

적절한 오류 처리는 "종과 휘파람"버전으로 강등해서는 안됩니다. 파일 Open ()가 시도/제외하고 출력 파일 핸들에 대한 참조를 유지하도록 콜백을 설정해야합니다. 쓰기 호출은 시도/제외하고 Callback_obj.close () 메소드가 있습니다. Retrlines ()가 명시 적으로 file_handle.close ()로 돌아올 때 사용합니다 (시도/제외) - 예를 들어 오류 처리를 실시 할 수 있습니다. 예를 들어 "| 파일이 암시 적으로 닫힐 때와 파일 핸들이 부족할 위험이 있는지 생각해야합니다.

Python 3.x ftplib.ftp.retrlines ()는 유니 코드 문자열 인 str 객체를 제공해야하며, 기본 인코딩이 Latin1이 아닌 한, 창문을 작성하기 전에 인코딩해야합니다. 상자. 예상 EBCDIC 코드에 유효한 모든 256 바이트 (2) 모든 바이트가있는 테스트 파일이 있어야합니다.

몇 가지 "위생"발언

  1. Python을 3.0 ( "개념 증명"릴리스)에서 3.1로 업그레이드하는 것을 고려해야합니다.

  2. 코드를 더 잘 이해하려면 "I"를 시퀀스 색인으로 만 "I"로 사용하고 3 년 이상 전에 Fortran에서 습관을 획득 한 경우에만 사용하십시오 :-)

  3. 지금까지 발견 된 두 가지 문제 (각 캐릭터에 라인 터미네이터를 추가하는 경우, 잘못된 라인 터미네이터)가 처음 테스트했을 때 나타 났을 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top