用python写一个下载文件的小工具


用python写一个下载文件的小工具

文章插图
 
Python
关于Python , 相信很多人都有所耳闻 。经过近三十年的发展 , 再加上近几年AI的兴起 , Python作为一种科学语言的流行程度急剧上升 。而Python语法简单、语句清晰的特点 , 可以让程序员把精力集中在业务逻辑上 , 减轻我们的压力 。毕竟人生苦短 , 我用Python 。看看Python之父--Guido van Rossum的发量 , 在对比下JAVA之父——James Gosling 。。。
用python写一个下载文件的小工具

文章插图
 
Python之父
用python写一个下载文件的小工具

文章插图
 
Java之父
 
开发环境
  • Python3.6.5
  • pip(Python包管理工具 , Python3.4以上版本都会自带)
  • 一个顺手的编辑器(像这种一百多行代码的小工具 , 随便一个编辑器都可以 , 推荐vsCode , 毕竟微软大法好)
需求分析我们需要做一个下载文件并压缩保存的小工具 , 最好能多个目的地址同时下载 。所以我们会用到以下功能:
  • ftp(引入paramiko包 , Python支持ftp的包)
  • threading(Python对多线程支持的包)
  • 配置文件(需要引入json包 , 来解析json格式的配置文件 , json格式简单明了而且解析方便 , 所以选择json格式配置文件)
  • os(要操作目录)
  • 需要记录日志(logging , Python日志相关的包)
  • zipfile(Python压缩zip文件需要用到的包)
开始撸代码引入必要的包import paramikoimport threadingimport jsonimport osimport sys from stat import S_ISDIR as isdirimport loggingimport zipfileimport time获取ftp连接#建立连接 , 获取sftp句柄def sftp_connect(username,password,host,port):global loggerclient = Nonesftp = Nonetry:client = paramiko.Transport((host,port))except Exception as error:logger.error(error)else:try:client.connect(username=username, password=password)except Exception as error:logger.error(error)else:sftp = paramiko.SFTPClient.from_transport(client)return client,sftp断开ftp连接#断开连接def disconnect(client):global loggertry:client.close()except Exception as error:logger.error(error)def check_local(localPath):global loggerif not os.path.exists(localPath):try:os.mkdir(localPath)except IOError as err:logger.error(err)从ftp服务器下载文件#下载方法def downLoad(client, sftp, remote, local):global logger#检查远程文件try:result = sftp.stat(remote)except IOError as err:error = '[ERROR %s] %s: %s' %(err.errno,os.path.basename(os.path.normpath(remote)),err.strerror)logger.error(error)else:if isdir(result.st_mode):dirname = os.path.basename(os.path.normpath(remote))local = os.path.join(local, dirname)#local = local.replace("\","/")check_local(local)for file in sftp.listdir(remote):sub_remote = os.path.join(remote, file)sub_remote = sub_remote.replace("\","/")downLoad(client, sftp,sub_remote,local)else:if os.path.isdir(local):local = os.path.join(local, os.path.basename(remote))try:sftp.get(remote, local)except IOError as err:logger.error(err)else:logger.info('[get] %s %s %s', remote, '==>', local)lock.acquire()global finishfinish += 1lock.release()logger.info('已下载 [%d] 个文件', finish)压缩文件#压缩文件def writeAllFileToZip(absDir,zipFile):global loggerfor f in os.listdir(absDir):absFile=os.path.join(absDir,f) #子文件的绝对路径if os.path.isdir(absFile): #判断是文件夹 , 继续深度读取 。zipFile.write(absFile) #在zip文件中创建文件夹logger.info('写入 %s 到压缩包 %s 成功', absFile, zipFile.filename)writeAllFileToZip(absFile,zipFile) #递归操作else: #判断是普通文件 , 直接写到zip文件中 。zipFile.write(absFile)logger.info('写入 %s 到压缩包 %s 成功', absFile, zipFile.filename)return主方法(程序入口)【用python写一个下载文件的小工具】if __name__ == "__main__":#日志logging.basicConfig(level=logging.INFO,format ='%(asctime)s - %(name)s - %(levelname)s - %(message)s')logger = logging.getLogger()logFormatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')handler = logging.FileHandler("log.txt")handler.setLevel(logging.INFO)handler.setFormatter(logFormatter)console = logging.StreamHandler()console.setLevel(logging.INFO)console.setFormatter(logFormatter)logger.addHandler(handler)#logger.addHandler(console)#锁lock = threading.Lock()#条件finish = 0#读取配置文件configFile = open('config.json')configs = json.loads(configFile.read())configFile.close()logger.info('工作目录:%s', configs['workDir'])#检查本地工作目录(父目录)check_local(configs['workDir'])threadList = []for config in configs['threads']:logger.info("=======================配置信息 start=============================")logger.info("HostAddress %s",config['HostAddress'])logger.info('Port %s', config['Port'])logger.info('Username %s',config['Username'])logger.info('Password %s',config['Password'])logger.info('RemotePath %s',config['RemotePath'])logger.info('LocalPath %s',config['LocalPath'])logger.info("=======================配置信息 end=============================")client,sftp = sftp_connect(config['Username'],config['Password'],config['HostAddress'],config['Port'])#创建本地目录check_local(config['LocalPath'])#多线程t = threading.Thread(target=downLoad, args=(client, sftp, config['RemotePath'], config['LocalPath']))t.start()threadList.Append(t)#单线程#downLoad(client, sftp, config['RemotePath'], config['LocalPath'])for t in threadList:t.join()#压缩# while threading.active_count() == 1:logger.info('=======================准备开始压缩==========================')#time.sleep(3)logger.info('==========================开始压缩 。。。==========================')check_local(configs['zipDir'])zipFilePath = os.path.join(configs['zipDir'], configs['zipName'] + '.zip')zipFile = zipfile.ZipFile(zipFilePath, 'w', zipfile.ZIP_DEFLATED, allowZip64=True)absZipFileDir = configs['workDir']writeAllFileToZip(absZipFileDir, zipFile)logger.info('==========================压缩完成==========================')#保留终端print("Press Enter to continue ...")input()


推荐阅读