使用 Python 和 ftplib.FTP 从 z/os 下载文本文件

2022-01-09 00:00:00 python ftp mainframe zos

问题描述

我正在尝试使用 Python 和 ftplib 从 z/os PDS 自动下载一些文本文件.

I'm trying to automate downloading of some text files from a z/os PDS, using Python and ftplib.

由于主机文件是 EBCDIC,我不能简单地使用 FTP.retrbinary().

Since the host files are EBCDIC, I can't simply use FTP.retrbinary().

FTP.retrlines(),当与 open(file,w).writelines 作为回调一起使用时,当然不提供 EOL.

FTP.retrlines(), when used with open(file,w).writelines as its callback, doesn't, of course, provide EOLs.

所以,对于初学者来说,我想出了这段对我来说看起来不错"的代码,但由于我是一个相对的 Python 菜鸟,任何人都可以提出更好的方法吗?显然,为了让这个问题保持简单,这不是最终的花里胡哨的事情.

So, for starters, I've come up with this piece of code which "looks OK to me", but as I'm a relative Python noob, can anyone suggest a better approach? Obviously, to keep this question simple, this isn't the final, bells-and-whistles thing.

非常感谢.

#!python.exe
from ftplib import FTP

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

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.

Update: Python 3.0, platform is MingW under Windows XP.

z/os PDS 具有固定的记录结构,而不是依赖行结尾作为记录分隔符.但是,z/os FTP 服务器在以文本模式传输时,会提供记录结尾,而 retrlines() 会去掉这些结尾.

z/os PDSs have a fixed record structure, rather than relying on line endings as record separators. However, the z/os FTP server, when transmitting in text mode, provides the record endings, which retrlines() strips off.

结束更新:

这是我修改后的解决方案,它将成为持续开发的基础(例如,删除内置密码):

Here's my revised solution, which will be the basis for ongoing development (removing built-in passwords, for example):

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+"
")
            pcfile.close()
        print ("Done: " + dir)
sess.quit()

感谢 John 和 Vinay

My thanks to both John and Vinay


解决方案

我在试图弄清楚如何从 z/OS 递归下载数据集时遇到了这个问题.多年来,我一直在使用简单的 python 脚本从大型机下载 ebcdic 文件.它实际上就是这样做的:

Just came across this question as I was trying to figure out how to recursively download datasets from z/OS. I've been using a simple python script for years now to download ebcdic files from the mainframe. It effectively just does this:

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

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

相关文章