• python ftplib模块使用


    Python中默认安装的ftplib模块定义了FTP类,可用来实现简单的ftp客户端,用于上传或下载文件。

    ftplib模块常用方法

    ftp登陆连接
    from ftplib import FTP            #加载ftp模块
    ftp=FTP()                         #设置变量
    ftp.set_debuglevel(2)             #打开调试级别2,显示详细信息
    ftp.connect("IP","port")          #连接的ftp sever和端口
    ftp.login("user","password")      #连接的用户名,密码
    print ftp.getwelcome()            #打印出欢迎信息
    ftp.cmd("xxx/xxx")                #进入远程目录
    bufsize=1024                      #设置的缓冲区大小
    filename="filename.txt"           #需要下载的文件
    file_handle=open(filename,"wb").write #以写模式在本地打开文件
    ftp.retrbinaly("RETR filename.txt",file_handle,bufsize) #接收服务器上文件并写入本地文件
    ftp.set_debuglevel(0)             #关闭调试模式
    ftp.quit()                        #退出ftp
     
    ftp相关命令操作
    ftp.cwd(pathname)                 #设置FTP当前操作的路径
    ftp.dir()                         #显示目录下所有目录信息
    ftp.nlst()                        #获取目录下的文件
    ftp.mkd(pathname)                 #新建远程目录
    ftp.pwd()                         #返回当前所在位置
    ftp.rmd(dirname)                  #删除远程目录
    ftp.delete(filename)              #删除远程文件
    ftp.rename(fromname, toname)#将fromname修改名称为toname。
    ftp.storbinaly("STOR filename.txt",file_handel,bufsize)  #上传目标文件
    ftp.retrbinary("RETR filename.txt",file_handel,bufsize)  #下载FTP文件

    FTP.quit()与FTP.close()的区别

    • FTP.quit():发送QUIT命令给服务器并关闭掉连接。这是一个比较“缓和”的关闭连接方式,但是如果服务器对QUIT命令返回错误时,会抛出异常。
    • FTP.close():单方面的关闭掉连接,不应该用在已经关闭的连接之后,例如不应用在FTP.quit()之后。

    下载、上传文件

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    # @Time    : 2018/8/6 17:17
    # @File    : ftpclient.py
    # @Software: PyCharm
    
    
    
    # FTP操作
    from ftplib import FTP  # 加载ftp模块
    from ftplib import error_perm
    from utils import file_util
    import os
    import time
    import socket
    from concurrent.futures import ThreadPoolExecutor
    
    host = '127.0.0.1'
    username = 'egon'
    password = '123456'
    file = '1.txt'
    port = 2111
    
    
    def ftpconnect(host, port, username, password):
        ftp = FTP()
        # ftp.set_debuglevel(2)         #打开调试级别2,显示详细信息
        ftp.encoding = 'utf-8'  # 解决中文编码问题,默认是latin-1
        try:
            ftp.connect(host, port)  # 连接
            ftp.login(username, password)  # 登录,如果匿名登录则用空串代替即可
            print(ftp.getwelcome())  # 打印欢迎信息
        except(socket.error, socket.gaierror):  # ftp 连接错误
            print("ERROR: cannot connect [{}:{}]" .format(host, port))
            return None
        except error_perm:  # 用户登录认证错误
            print("ERROR: user Authentication failed ")
            return None
        return ftp
    
    
    def is_ftp_file(ftp_conn, ftp_path):
        try:
            if ftp_path in ftp_conn.nlst(os.path.dirname(ftp_path)):
                return True
            else:
                return False
        except error_perm:
            return False
    
    
    def downloadfile(ftp, remotepath, localpath):
        """
         下载文件
        :param ftp:
        :param remotepath:
        :param localpath:
        :return:
        """
        bufsize = 1024  # 设置缓冲块大小
        fp = open(localpath, 'wb')  # 以写模式在本地打开文件
    
        res = ftp.retrbinary(
            'RETR ' + remotepath,
            fp.write,
            bufsize)  # 接收服务器上文件并写入本地文件
        if res.find('226') != -1:
            print('download file complete', localpath)
        ftp.set_debuglevel(0)  # 关闭调试
        fp.close()  # 关闭文件
    
    
    def uploadfile(ftp, remotepath, localpath):
        """
        上传文件
        :param ftp:
        :param remotepath:
        :param localpath:
        :return:
        """
        bufsize = 1024
        fp = open(localpath, 'rb')
        res = ftp.storbinary('STOR ' + remotepath, fp, bufsize)  # 上传文件
        if res.find('226') != -1:
            print('upload file complete', remotepath)
        ftp.set_debuglevel(0)
        fp.close()
    def ftp_theadpool(func, ftp, file_list):
        """
        通过线程池调用上传文件列表
        :param func:
        :param file_list:
        :return:
        """
        pool = ThreadPoolExecutor(6)
        for remotepath, localpath in file_list:
            pool.submit(func, ftp, remotepath, localpath)
        pool.shutdown()
    
    
    if __name__ == "__main__":
        ftp = ftpconnect(host, port, username, password)
        file_list = ftp.nlst()
        print(file_list)
        # 将传输模式改为二进制模式 ,避免提示 ftplib.error_perm: 550 SIZE not allowed in ASCII
        # mode错误
        ftp.voidcmd('TYPE I')
        file_size = ftp.size("sqldeveloper-3.1.07.42.zip")  # 文件大小
    
        print('filesize [{}]'.format(file_util.bytes2human(file_size)))
        start = time.time()
        downloadfile(ftp, "sqldeveloper-3.1.07.42.zip", "e:/x.zip")
        end = time.time()
        print('consume time [{}]'.format(end - start))
    
        if '20180910' not in file_list:  # 创建目录
            res = ftp.mkd('20180910')
            print('mk ', res)
    
    
        ftp.cwd('20180910')  # 进入到新目录
        print("FTP当前路径:", ftp.pwd())
        print("文件信息:", ftp.nlst())
    
        uploadfile(ftp, "testup.zip", "e:/x.zip") # 上传文件
        # ftp.cwd('20180910')
        # pwd_path = ftp.pwd()
        # print("FTP当前路径:", pwd_path)
        # print("文件信息:", ftp.nlst())
        ftp.quit()
    

      

    带进度条下载文件

    from ftplib import FTP
    from ftplib import error_perm
    import os
    import socket
    import os
    import time
    from utils import my_logset
    from utils.time_utils import run_time
    import sys
    import math
    from utils import file_util
    
    """
    ftp操作上传和下载
    """
    
    
    class FTP_OPS(object):
        """
        ftp文件操作
        """
    
        def __init__(self, log_file, ftp_ip, ftp_port, ftp_user, ftp_pwd):
            self.db_log = my_logset.get_mylogger("ftp", log_file)
            self.ftp_ip = ftp_ip
            self.ftp_port = ftp_port
            self.ftp_user = ftp_user
            self.ftp_pwd = ftp_pwd
    
        def ftp_connect(self):
            """
            连接ftp
            :return:
            """
            socket.setdefaulttimeout(160)  # 超时FTP时间设置为60秒
            ftp = FTP()
            ftp.connect(host=self.ftp_ip, port=self.ftp_port)
            ftp.set_debuglevel(2)  # 开启调试模式
            ftp.encoding = 'utf-8'
    
            try:
                ftp.login(self.ftp_user, self.ftp_pwd)
                self.db_log.info(
                    '[{}]login ftp {}'.format(
                        self.ftp_user,
                        ftp.getwelcome()))  # 打印欢迎信息
    
            except(socket.error, socket.gaierror):  # ftp 连接错误
                self.db_log.warn(
                    "ERROR: cannot connect [{}:{}]".format(
                        self.ftp_ip, self.ftp_port))
                return None
    
            except error_perm:  # 用户登录认证错误
                self.db_log.warn("ERROR: user Authentication failed ")
                return None
            except Exception as e:
                print(e)
                return None
            return ftp
    
        @run_time
        def upload_file(self, ftp: FTP, remotepath: str,
                        localpath: str, file: str):
            """
             # 从本地上传文件到ftp
            :param ftp: ftp对象
            :param remotepath: ftp远程路径
            :param localpath: 本地
            :return:
            """
            flag = False
            buffer_size = 10240  # 默认是8192
            print(ftp.getwelcome())  # 显示登录ftp信息
    
            fp = open(os.path.join(localpath, file), 'rb')
    
            try:
                ftp.cwd(remotepath)  # 进入远程目录
                self.db_log.info(
                    "found folder [{}] in ftp server, upload processing.".format(remotepath))
                print('进入目录', ftp.pwd())
                # 将传输模式改为二进制模式 ,避免提示 ftplib.error_perm: 550 SIZE not allowed in
                # ASCII
                ftp.voidcmd('TYPE I')
                ftp.storbinary('STOR ' + file, fp, buffer_size)
                ftp.set_debuglevel(0)
                self.db_log.info("上传文件 [{}] 成功".format(file))
                flag = True
            except error_perm as e:
                self.db_log.warn('文件[{}]传输有误,{}'.format(file, str(e)))
            except TimeoutError:
                self.db_log.warn('文件[{}]传输超时'.format(file))
                pass
            except Exception as e:
                self.db_log.warn('文件[{}]传输异常'.format(file, str(e)))
                pass
            finally:
                fp.close()
    
            return {'file_name': file, 'flag': flag}
    
        def download_file(self, ftp_file_path, dst_file_path):
            """
            从ftp下载文件到本地
            :param ftp_file_path: ftp下载文件
            :param dst_file_path: 本地存放
            :return:
            """
            buffer_size = 10240  # 默认是8192
            ftp = self.ftp_connect()
            print(ftp.getwelcome())  # 显示登录ftp信息
    
            # 将传输模式改为二进制模式 ,避免提示 ftplib.error_perm: 550 SIZE not allowed in ASCII
            ftp.voidcmd('TYPE I')
            remote_file_size = ftp.size(ftp_file_path)  # 文件总大小
    
            print('remote filesize [{}]'.format(remote_file_size))
            cmpsize = 0  # 下载文件初始大小
            lsize = 0
            # check local file isn't exists and get the local file size
            if os.path.exists(dst_file_path):
                lsize = os.stat(dst_file_path).st_size
            if lsize >= remote_file_size:
                print('local file is bigger or equal remote file')
                return
            start = time.time()
            conn = ftp.transfercmd('RETR {0}'.format(ftp_file_path), lsize)
    
            f = open(dst_file_path, "ab")
            while True:
                data = conn.recv(buffer_size)
                if not data:
                    break
                f.write(data)
                cmpsize += len(data)
                self.progressbar(cmpsize, remote_file_size)
                # print(
                #      ''*30, 'download process:%.2f%%' %
                #     (float(cmpsize) / remote_file_size * 100))
                # ftp.retrbinary(
                #     'RETR {0}'.format(ftp_file_path),
                #     f.write,
                #     buffer_size)
            f.close()
            try:
                ftp.voidcmd('NOOP')
                print('keep alive cmd success')
                ftp.voidresp()
                print('No loop cmd')
                conn.close()
                ftp.quit()
            except Exception as e:
                pass
            finally:
                end = time.time()
                print('consume time [{}]'.format(end - start))
                file_size = os.stat(dst_file_path).st_size
                print('local filesize [{}] md5:[{}]'.format(
                    file_size, file_util.get_md5(dst_file_path)))
    
            def progressbar(cur, total):
                """
                  进度条显示
                  cur表示当前的数值,total表示总的数值。
                :param cur:
                :param total:
                :return:
                """
                percent = '{:.2%}'.format(cur / total)
                sys.stdout.write('
    ')
                sys.stdout.write('[%-50s] %s' %
                                 ('=' * int(math.floor(cur * 50 / total)), percent))
                sys.stdout.flush()
                if cur == total:
                    sys.stdout.write('
    ')
    
    
    if __name__ == '__main__':
        host = "10.0.0.1"
        username = "test"
        password = "test"
        port = "21"
        ftp_file_path = "/data/an/1.zip"
        dst_file_path = "/data/tmp/1.zip"
        ftp = FTP_OPS(host=host, username=username, password=password, port=port)
        ftp.download_file(ftp_file_path=ftp_file_path, dst_file_path=dst_file_path)

      

  • 相关阅读:
    BZOJ2762: [JLOI2011]不等式组
    BZOJ1452: [JSOI2009]Count
    Codeforces Round #441 (Div. 2, by Moscow Team Olympiad)
    BZOJ1635: [Usaco2007 Jan]Tallest Cow 最高的牛
    BZOJ2730: [HNOI2012]矿场搭建
    Flask实现异步非阻塞请求功能
    在flask中使用websocket-实时消息推送
    Python数据库连接池DBUtils
    flask请求上下文
    scanf与getchar
  • 原文地址:https://www.cnblogs.com/xiao-apple36/p/9675185.html
Copyright © 2020-2023  润新知