之前写的很多爬虫因为有针对性,不适合分享,最近写了一个上传文件夹的小工具,东西不大,功能尚可,配置还比较方便,打包也很方便分享一下
# --coding:utf-8--
from paramiko import Transport,SFTPClient,SSHException
from os import path,listdir,rmdir,remove
from sys import argv
from time import sleep
from json import loads
# SFTP_CONFIG={}
# SFTP_CONFIG["REMOTE_IP_ADRESS"] = "127.0.0.1"
# SFTP_CONFIG["REMOTE_PORT"] = 22
# SFTP_CONFIG["SFTP_USERNAME"] ="admin"
# SFTP_CONFIG["SFTP_PASS"] ="admin"
#
# FILE_CONFIG={}
# FILE_CONFIG["LOCAL_DIR"] = "./uptest/"
# FILE_CONFIG["REMOTE_DIR"] ="/root/autouploadtest/"
#
# DELETE_FILE = False
Transport._preferred_compression= ('zlib',)
class SFTP_helper():
def __init__(self,sftp_conf,file_conf,delete=False):
self.ftpclient = self.get_sftp_client(sftp_conf)#其他程序调用时候 判断这个是否是None来确定连接是否成功
self.local_dir = file_conf["LOCAL_DIR"]
self.remote_dir = file_conf["REMOTE_DIR"]
self.delete_file = delete
@staticmethod
def get_sftp_client(sftp_conf):
"""
尝试连接SFTP服务器,这里连接错误是没抛出去的,可以根据需要修改
:param sftp_conf:一个配置dict对象
:return:
"""
try:
transport = Transport((sftp_conf["REMOTE_IP_ADRESS"],sftp_conf["REMOTE_PORT"]))
transport.connect(username=sftp_conf["SFTP_USERNAME"], password=sftp_conf["SFTP_PASS"])
sftp = SFTPClient.from_transport(transport)
return sftp
except SSHException as sshe:
print("链接失败,请检查链接参数:",sshe)
return None
def upload_file(self,fromfile,tofile):
"""
上传文件的具体执行函数,注意都是绝对路径
:param fromfile: 被发送的文件完整路径包括文件本身
:param tofile: 发送到的地址,包括文件本身!!!
:return:
"""
if self.ftpclient:
# print(fromfile,tofile)
self.ftpclient.put(fromfile,tofile)
return True
else:
return False
def upload_folder(self,fromd=None,tod=None):
"""
默认情况就调用helper内部维护的文件夹,传递的话就用传递的
:param fromd: 文件夹
:param tod: 文件夹
:return:
"""
# 默认参数设置
fromdir = path.abspath(self.local_dir) if not fromd else path.abspath(fromd)
todir = path.abspath(self.remote_dir) if not tod else path.abspath(tod)
# 尝试远端创建相关文件夹,远端已有的情况下 会报错
try:
print("mkdir ",path.abspath(todir))
self.ftpclient.mkdir(path.abspath(todir))
sleep(2)
except:
print("创建远端文件夹失败")
#初级防呆设计
if self.ftpclient==None:
print("远端链接失败!! 任务中止!!!")
return
print( "文件从:",fromdir," 发送到:",todir)
for file in listdir(fromdir):
tempfrom = path.join(fromdir,file)
tempto = path.join(todir,file)
if path.isdir(tempfrom):
print("子文件夹上传", tempfrom, tempto)
self.upload_folder(tempfrom,tempto)
else:
print("上传文件",tempfrom,tempto)
self.upload_file(tempfrom,tempto)
print("#######文件上传完毕#######")
def clean_folder(self,cleanf=None):
"""
用来清理发送的文件夹,正常情况下不用这个
:param cleanf:
:return:
"""
if self.delete_file !=True:
print("配置中禁止了清理文件,退出...")
return
cleanfolder = path.abspath(cleanf) if cleanf else path.abspath(self.local_dir)
#初级防呆设计,不能删除所在文件夹等
if cleanfolder == path.dirname("/") or cleanfolder == path.dirname("/root") or cleanfolder == path.dirname("/home") or cleanfolder == path.dirname("./"):
print("《安全预防》:不能清理高级目录或当前目录:",cleanfolder)
return
else:
for file in listdir(cleanfolder):
temppath = path.join(cleanfolder,file)
if path.isdir(temppath):
print("清除文件夹")
self.clean_folder(temppath)
rmdir(temppath)
else:
print("删除:", path.join(cleanfolder, file))
remove(path.join(cleanfolder,file))
#简单加载 JSON文件作为配置
def load_json(filepath):
with open(filepath,"r") as f:
total = loads(f.read())
# print(total)
return total["SFTP_CONFIG"],total["FILE_CONFIG"],total["DELETE_FILE"]
if __name__ == '__main__':
# 从运行参数里拿到配置json文件位置,默认的话使用./sftp_config.json
if len(argv)>1:
print("使用自定义的配置")
configpath = argv[1]
if not path.isfile(configpath):
print("配置文件位置指定错误~!无法执行,退出......")
exit(1)
else:
configpath = "./sftp_config.json"
print("使用配置文件:",configpath)
try:
sftpconf, fileconf, deleteflag = load_json(configpath)
except KeyError as e:
print("配置文件有问题,已退出......",e)
exit(1)
helper = SFTP_helper(sftpconf, fileconf, deleteflag)
helper.upload_folder()
helper.clean_folder()
这里简单的写了一个使用逻辑,可以配合linux 下的crontab定时任务直接做到定时上传,还不占内存,有需要的小伙伴改一改就可以做到自己的功能里了。
打包的话使用pyinstaller -F xxx.py 就可以了,我的这个打包完以后18MB左右,运行速度没啥问题,就是上传成功否还没判断可以根据需要自己设计了。