【发布时间】:2010-11-14 03:58:32
【问题描述】:
我正在尝试使用 Python 和 ftplib 从 z/os PDS 自动下载一些文本文件。
由于主机文件是 EBCDIC,我不能简单地使用 FTP.retrbinary()。
FTP.retrlines(),当与 open(file,w).writelines 作为回调一起使用时,当然不提供 EOL。
所以,对于初学者来说,我想出了这段“对我来说看起来不错”的代码,但由于我是一个相对的 Python 菜鸟,任何人都可以提出更好的方法吗?显然,为了让这个问题保持简单,这不是最终的花里胡哨的事情。
非常感谢。
#!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()
感谢约翰和维奈
【问题讨论】:
-
请编辑您的问题以提及和描述 PDS 文件。 “一些文本文件”相当不够。
-
另外请说明什么平台,什么版本的 Python,以及为什么你的 writelineswitheol 方法会附加 '\r\n' 而不是 '\n'。并请说明您是否实际运行过此程序并检查输出以确保它具有适合您平台的正确线路终止。
-
完成。我在 corp.firewall 外面的家里做一些周末编码,所以我只会在本周晚些时候测试这个想法。