1

多年来,我一直在使用一个非常简单的批处理文件从 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

4 回答 4

6

就像我写一个问题时通常发生的那样,我可以去寻找答案。我想删除这个问题而不是回答它,但我认为可能有像我这样的其他人可以使用这个答案,所以我将发布Fredrik Lundh从这个网页上拿走的内容。

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

基本上,retrlines 一次从服务器检索一行(在下面的脚本中,我正在编写该行,因为它添加了换行符。

我不太了解 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()
于 2013-01-08T22:16:38.147 回答
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')
于 2016-04-13T14:25:54.463 回答
0

我在看这个,想知道为什么 ftplib 的创建者决定首先去掉换行符。我四处搜索并没有找到满意的答案,所以我想知道是否进入 ftplib 并更改代码 - 这对我来说似乎比我的第一个答案更简单。因此我在 C:\Python27\Lib 中找到了 ftplib.py 文件

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

    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 时要少。不确定这是否是一个很好的做法,但浏览这些函数并从中学习一些东西很有趣。

于 2013-01-08T23:54:38.660 回答
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()
于 2020-05-28T20:19:19.287 回答