Python-FTP下载目录中的所有文件

Sos*_*sti 26 python ftp ftplib

Python newb在这里请耐心等待.我正在整理一个脚本,通过FTP下载目录中的所有文件.到目前为止,我已经设法连接并获取一个文件,但我似乎无法批量工作(从目录中获取所有文件)这是我到目前为止:

from ftplib import FTP
import os, sys, os.path

def handleDownload(block):
    file.write(block)
    print ".",

ddir='C:\\Data\\test\\'
os.chdir(ddir)
ftp = FTP('test1/server/')

print 'Logging in.'
ftp.login('user1\\anon', 'pswrd20')
directory = '\\data\\test\\'

print 'Changing to ' + directory
ftp.cwd(directory)
ftp.retrlines('LIST')

print 'Accessing files'

for subdir, dirs, files in os.walk(directory):
    for file in files: 
        full_fname = os.path.join(root, fname);  
        print 'Opening local file ' 
        ftp.retrbinary('RETR C:\\Data\\test\\' + fname,
                       handleDownload,
                       open(full_fname, 'wb'));
        print 'Closing file ' + filename
        file.close();
ftp.close()
Run Code Online (Sandbox Code Playgroud)

我打赌你可以告诉我,当我运行它时它没有做太多,所以任何改进建议都将非常感激

PS这不是作业:DD

谢谢!!

小智 64

我已经设法破解了这个,所以现在为未来的访问者发布相关的代码:

filenames = ftp.nlst() # get filenames within the directory
print filenames

for filename in filenames:
    local_filename = os.path.join('C:\\test\\', filename)
    file = open(local_filename, 'wb')
    ftp.retrbinary('RETR '+ filename, file.write)

    file.close()

ftp.quit() # This is the “polite” way to close a connection
Run Code Online (Sandbox Code Playgroud)

这适用于Python 2.5,Windows XP.

  • filenames = ftp.nlst() (8认同)
  • 推荐的方法是使用:`ftp.quit()`而不是`ftp.close()`.请[见这个链接](https://docs.python.org/2/library/ftplib.html#ftplib.FTP.quit) (3认同)

sar*_*old 7

如果这只是你想要解决的问题,我可能会建议这个wget命令:

cd c:\destination
wget --mirror --continue --no-host-directories --user=username --password=s3cr3t ftp://hostname/source/path/
Run Code Online (Sandbox Code Playgroud)

--continue如果服务器上的文件发生更改,则该选项可能非常危险.如果只添加文件,那么它非常友好.

但是,如果这是一个学习练习,你想让你的程序工作,我认为你应该从这一行开始:

for subdir, dirs, files in os.walk(directory):
Run Code Online (Sandbox Code Playgroud)

directory在您的大多数程序中一直是远程源目录,但该os.walk()函数无法遍历远程目录.您需要使用提供给retrlines函数的回调自己迭代返回的文件.

看一下MLSD或者NLST选项而不是LIST,它们可能更容易解析.(请注意,FTP实际上并没有指定列表的外观;它总是打算由控制台上的人驱动,或者传输特定的文件名.因此,使用FTP列表做聪明事情的程序会将它们呈现给用户对于奇怪或模糊的服务器,GUI可能必须拥有大量的特殊情况代码.当面对恶意文件名时,他们可能都会做一些愚蠢的事情.)

你能用sftp吗?sftp 确实有一个关于如何解析文件列表的规范,不清楚地传输用户名/密码,并且没有被动与活动连接的巨大烦恼 - 它只是使用单一连接,这意味着它比FTP更适用于防火墙.

编辑:您需要将"可调用"对象传递给该retrlines函数.可调用对象是定义__call__方法的类的实例,或者是函数.虽然函数可能更容易描述,但类的实例可能更有用.(您可以使用实例来收集文件名,但该函数必须写入全局变量.不好.)

这是最简单的可调用对象之一:

>>> class c:
...  def __call__(self, *args):
...   print(args)
...
>>> f = c()
>>> f('hello')
('hello',)
>>> f('hello', 'world')
('hello', 'world')
Run Code Online (Sandbox Code Playgroud)

这将创建一个新类,c用于定义实例方法__call__.这只是以相当愚蠢的方式打印它的参数,但它显示了我们谈论的最小化.:)

如果你想要更聪明的东西,它可以做这样的事情:

class handle_lines:
  def __init__(self):
    self.lines = []
  def __call__(self, *args):
    self.lines << args[0]
Run Code Online (Sandbox Code Playgroud)

iterlines使用此类的对象调用,然后查看对象的lines成员以获取详细信息.