如何使用ftplib正确下载文件,以便为Windows添加换行符

时间:2013-01-08 21:10:59

标签: python newline ftplib

我一直使用非常简单的批处理文件从UNIX ftp服务器上下载数百万个文件

login
passwd
ascii
prompt n
cd to the right directory
get some_file
get another_file
cd to the next directory
repeat the pattern

关于这个的好处是它很简单,并且所有文件都使用Window的换行符到达,因此文件已准备好与我现有的程序一起使用。由于我的路由器发生了一些变化,我不得不编写一个Python脚本来提取文件 - 我的第一个版本的脚本非常简单 - 但它可以正常工作

for key in key_filings:
   for filing in key_filings[key]:
        remote_directory = '/foo/bar/' + key + '/' + filing['key_number']
        ftp.cwd(remote_directory)
        text_file = filing['txt']
        ftp.retrlines('RETR '+ text_file, open(save_dir + text_file,'w').writelines)
        hdr_file = filing['hdr']
        ftp.retrlines('RETR ' + hdr_file, open(save_dir + hdr_file,'w').writelines)

但是,文件没有任何明显的换行符。这些文件存储在unix系统中。在我使用Windows CMD shell下载文件之前,换行符就在那里。我已经尝试发送ASCII命令,但正如预期的那样没有任何影响。

至关重要的是,我能够访问最初存在的换行符,因为我的一些代码处理是基于行的。

4 个答案:

答案 0 :(得分:6)

通常情况下,当我写出问题时,我可以找到答案。我想删除问题而不是回答问题,但我认为可能有其他像我这样的人可以使用答案,所以我将发布Fredrik Lundh从webpage发布的内容。

我想保存文件,而不是像在脚本中那样将其打印到屏幕上

基本上,后退是从服务器一次检索一行(在下面的脚本中我正在写行,因为它在到达时添加了换行符。

我真的不了解lamda函数或回调是什么,所以这是最终围绕这些概念的借口。

import ftplib
ftp = ftplib.FTP('ftp.some.site', user = 'username', passwd = 'password_for_username')

for key in key_filings:
    for filing in key_filings[key]:
        remote_directory = '/foo/bar/' + key + '/' + filing['key_number']
        ftp.cwd(remote_directory)
        text_file = filing['txt']
        save_text_ref = open(save_dir + text_file, 'w')
        ftp.retrlines('RETR '+ text_file, lambda s, w = save_text_ref.write: w(s+'\n'))
        save_text_ref.close()
        hdr_file = filing['hdr']
        save_hdr_ref = open(save_dir +hdr_file,'w')
        ftp.retrlines('RETR ' + hdr_file, lambda s, w = save_hdr_ref.write: w(s+'\n'))
        save_hdr_ref.close()

答案 1 :(得分:3)

爱PyNEwbie使用lambda,谢谢。以下是相同代码的更通用版本 - 尝试将此作为评论添加到您的帖子中,但不会占用代码:

from ftplib import FTP

def ftp_download_textfile(host, user, passwd, subdir, filename):
    ftp = FTP(host, user=user, passwd=passwd)
    ftp.cwd(subdir)
    fp = open(filename, 'w')
    ftp.retrlines('RETR ' + filename, lambda s, w = fp.write: w(s + '\n'))
    fp.close()

ftp_download_textfile('ftp.example.com', 'skywalker', 'maltesefalcon',
                      'spec/files', 'secretplans.csv')

答案 2 :(得分:0)

我正在看这个,并想知道为什么ftplib的创建者决定首先删除新的行字符。我用Google搜索并没有找到满意的答案,所以我想知道进入ftplib并更改代码 - 这对我来说似乎更简单,然后是我的第一个答案。因此我在C:\ Python27 \ Lib

中找到了ftplib.py文件

我制作了一份名为ftplib_myMOD.py的副本,然后在IDLE中打开它。并找到了后退功能并对其进行了修改

    fp = conn.makefile('rb')
    while 1:
        line = fp.readline()
        if self.debugging > 2: print '*retr*', repr(line)
        if not line:
            break
        #if line[-2:] == CRLF:  Commented out
         #   line = line[:-2]   Commented out
        #elif line[-1:] == '\n': Commented out
          #  line = line[:-1]    commented out

保存文件,关闭IDLE并重新启动它。执行此操作并导入后

import ftplib_MYMOD as myftp

我发现线条断裂存在。

我喜欢这种方法,因为这意味着我使用的步骤比使用lambda时少。不确定它是否是完全好的做法,但通过查看函数并从中学习一些东西很有趣。

答案 3 :(得分:0)

为什么CRLF被剥夺真是太奇怪了。我在IBM iSeries DB2上尝试过。最终这样做是为了避免每次读取的行都对磁盘文件进行I / O。

lines = []
ftp.retrlines('RETR ' + remote_file, lambda d:lines.append(d+'\n'))
f=open(yourfile,'w')
f.writelines(lines)
f.close()