python基础5-模块定义、导入方法、import本质、time和datetime、random、os、sys、shutil、shelve、xml、ConfigParser、hashlib、re

1、 定义

模块的定义:用来从逻辑上组织python代码(变量、函数、类、逻辑:实现一个功能),本质上就是.py结尾的python文件(文件名:test.py,对应的模块名:test)

包的定义:用来从逻辑上组织模块,本质就是一个目录(文件夹),必须带有一个_ _ init _ _().py的文件

2、使用方法(导入方法)

import module_name
import module1_name, module2_name
from module_name import * # 不建议使用
from module_name import logger as log
from . import test # 从当前目录下导入test,用在导入包下的模块,写在__init__.py文件中

3、import的本质

就是把python文件解释一遍

import module_name	--> modle_name = all_code
from module_name import name	-->	进入module_name文件找到name

导入包的本质:就是解释包下面的_ _ init _ _.py文件
要想导入包中的文件需要在init中导入模块即可

这里存在一个问题就是,模块和要导入模块的文件不在同一个目录下该怎么办呢?看下面怎么解决这个问题

import sys,os
print(sys.path) # 导入模块时,是在这个列表中的路径中查找我们要导入的模块的
os.path.abspath(__file__) # 获得当前文件的绝对路径
os.path.dirname(os.path.abspath(__file__)) # 获取上一层的绝对路径
sys.path.append(os.path.dirname(os.path.abspath(__file__))) # 加入列表

上面的方法,我们就可以找到需要导入的模块的位置

4、导入优化

from module import test # 相比于import module速度更快 

5、模块的分类

a.标准库
b.开源模块
c.自定义模块

自定义模块和开源模块的使用参考: http://www.cnblogs.com/wupeiqi/articles/4963027.html

6、内置模块

time和datetime模块

在python中,通常有这几种方式来表示时间:
a.时间戳
时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。用time.time()来获得这个偏移量,返回的是float类型,单位是秒。
注:1970年是unix诞生年

xue@xue-MacBookAir:~$ python3
Python 3.5.2 (default, Oct  8 2019, 13:06:37) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import time
>>> time.time()
1577024037.3293345
>>> 1577024037.3293345/3600/24/365
50.0071041771098
>>> 1970+50
2020
>>> 

b.格式化的时间字符串

c.元组(struct_time)共九个元素
UTC(Coordinated Universal Time)即格林威治天文时间,世界标准时间。在中国为UTC+8(东八区,全球24个时区),比标准时间早8小时。DST(Daylight Saving Time)即夏令时。

>>> import time
>>> time.localtime()
time.struct_time(tm_year=2019, tm_mon=12, tm_mday=22, tm_hour=22, tm_min=24, tm_sec=23, tm_wday=6, tm_yday=356, tm_isdst=0) 

tm_wday:一个星期中的第几天,tm_yday:一年中的第几天,tm_isdst:是不是夏令时

time.timezone # 当地时间和世界标准时间的差值,单位秒
time.gmtime() # 无参时,是把本地的时间传入,转换成struct_time,返回值是0区的时间
time.localtime() # 无参时,传入的是本地时间,转换成struct_time,返回值是本地的时间
	x = time.localtime()
	x.tm_year
time.mktime(struct_time) # struct_time转换成时间戳
time.strftime(format, struct_time) # struct_time转换成格式化的时间字符串
	time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
time.strptime(str, format) # 格式化的时间字符串转换成struct_time
	time.strftime('2019-12-22 23:12:32', "%Y-%m-%d %H:%M:%S")

time.asctime() # struct_time--->str
time.ctime() # timestamp--->str

在这里插入图片描述
在这里插入图片描述

import datetime
datetime.datetime.now() # 获取当前的时间
datetime.datetime.now()+datetime.timedelta(3) # 当天时间+3天
datetime.datetime.now()+datetime.timedelta(-3) # 当天时间-3天
datetime.datetime.now()+datetime.timedelta(hours=3) # 当天时间+3h
datetime.datetime.now()+datetime.timedelta(hours=-3) # 当天时间-3h
datetime.datetime.now()+datetime.timedelta(minutes=3) # 当天时间+3分钟

c_time = datetime.datetime.now()
c_time.replace(hour=3, minute=30) # 时间的替换

random模块

import random
random.random() # [0, 1)之间的一个随机浮点数
random.randint(1, 3) # [1, 3]之间的一个随机整数
random.uniform(1, 3) # (1, 3)之间的随机浮点数
random.randrange(1, 10, 2) # [1, 10)之间的一个随机整数,步数为2,步数不写,默认为1
random.choice()
	random.choice("helloworld")
	random.choice(["1","2","3","4","6","8","9"])
	random.choice(("1","2","3","4","6","8","9"))
random.sample()
	random.sample("hello") # 从前面的序列中,随机的取两位返回
	random.shuffle(items) # 打乱顺序

实际应用:

#随机选取0到100间的偶数
random.randrange(0, 100, 2) # 4
	
#随机浮点数
random.random() #0.2784394798375937597
random.uniform(1, 10) # 9.435457568567835

# 随机字符
random.choice('asdsfdeerdgs') # f

#多个字符中选取特定数量的字符
random.sample('asdfghjkl', 3) # ['d', 'g', 'h']

#随机选取字符串
random.choice(['apple', 'pear', 'banana', 'lemon']) # apple

#洗牌
items = [1,2,3,4,5,6,7,8]
random.shuffle(items)

随机验证码的功能

# Author: Mr.Xue
# 2019.10.25
	
import random
	
checkcode = ''
	
for i in range(4):
	tmp = random.randint(0,1)
	if tmp == 1:
		tmp2 = chr(random.randint(65, 90)) # ['A', 'Z']
		checkcode += tmp2
	else:
		tmp2 = random.randint(0, 9)	
		checkcode += str(tmp2)
print(checkcode)	

os模块

提供对操作系统进行调用的接口

os.getcwd() # 获取当前的工作目录,返回str
os.chdir("dirname") # 切换目录
os.curdir # 返回当前目录
os.pardir # 返回上一级目录
os.makedirs('dirname1/dirname2/dirname3') # 递归创建多级目录
os.removedirs('dirname1') # 若目录为空,则删除,并递归到上一级目录,如若也为空,也删除,以此类推
os.mkdir('dirname') # 生成单级目录
os.rmdir('dirname') # 删除单级目录,若目录不为空则无法删除,报错
os.listdir('dirname') # 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表形式打印
os.remove() # 删除一个文件
os.rename('oldname', 'newname') # 重命名文件/目录
os.stat('path/filename') # 获取文件/目录信息
os.sep # 输出操作系统特定的路径分隔符,win下为"\\",linux下为"/"
os.linesep # 输出当前平台使用的行终止符,win下为"\r\n",linux下为"\n"
os.pathsep # 输出用于分割文件路径的字符串,win下为";",linux下为":"
os.environ # 获取系统环境变量,返回一个字典类型
os.name # 输出字符串指示当前使用平台,win下为'nt',linux下为'posix'
os.system("bash command") # 执行shell命令
os.path.abspath(path) # 返回path的绝对路径
os.path.split(path) # 将path分割成目录和文件名,返回一个元组
os.path.dirname(path) # 返回目录,即文件所在的路径
os.path.basename(path) # 返回path最后的文件名,如果path以'/'或'\'结尾,则返回空值
os.path.exists(path) # 如果path存在则返回True,否则返回False
os.path.isabs(path) # 如果path是绝对路径,返回True,否则返回False
os.path.isfile(path) # 如果path是一个存在的文件,则返回True,否则返回False
os.path.isdir(path) # 如果path是一个存在的目录,则返回True,否则返回False
os.path.join(path1[, path2[, ...]]) # 将多个路径组合后返回
	os.path.join(r'C:', r'\a.txt')
os.path.getatime(path) # 返回path所指向的文件或目录的最后存取时间
os.path.getmtime(path) # 返回path所指向的文件或目录的最后修改时间

sys模块

sys.argv # 命令行参数List,第一个元素是程序本身的路径
	# test.py
	import sys
	print(sys.argv)

	python3 test.py 1 2 3 4
		
sys.exit(n) # 退出程序,正常退出是exit(0)
sys.version # 获取python解释程序的版本信息
sys.maxint # 最大的Int值
sys.path # 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform # 返回操作系统平台名称
sys.stdout.write('please:')
val = sys.stdin.readline()[:-1]

shutil模块

高级的文件、文件夹、压缩包 处理模块

shutil.copyfileobj(fsrc, fdst[, length]) # 把文件内容拷贝到另一个文件中,可以部分内容
	# 源码如下
	def copyfileobj(fsrc, fdst, length=16*1024):
	"""copy data from file-like object fsrc to file-like object fdst"""
	while 1:
		buf = fsrc.read(length)
		if not buf:
			break
		fdst.write(buf)
	
	# example
	import shutil
	f1 = open("本节笔记", encoding="utf-8")
	f2 = open("笔记2", "w", encoding="utf-8")
	shutil.copyfileobj(f1, f2)
shutil.copyfile(src, dst) # 拷贝文件
	# 直接传入文件名,就可以实现copy
	shutil.copyfile("笔记1", "笔记2")
shutil.copymode(src, dst) # 仅拷贝权限,内容、组、 均不变
shutil.copystat(src, dst) # 拷贝状态的信息,包括:mode bits, atime, mtime, flags
shutil.copy(src, dst) # 拷贝文件和权限
shutil.copy2(src, dst) # 拷贝文件和状态信息
shutil.copytree(src, dst, symlink=False, ignore=None) # 递归的去拷贝文件目录和文件
shutil.rmtree(dst) # 删除目录
shutil.move(src, dst) # 递归的去移到文件
"""
创建压缩包并返回文件路径,例如:zip、tar
base_name: 压缩包的文件名,也可以是压缩包的路径,只是文件名时,则保存至当前目录,否则保存至指定路径,如:www ---> 保存至当前路径;如:/User/xue/www  ---> 保存至/User/xue
format: 压缩包种类,如:zip, tar
root_dir: 要压缩的文件夹路径(默认当前目录)
owner: 用户,默认当前用户
group: 组,默认当前组
logger: 用于记录日志,通常是logging.Logger对象
"""
shutil.make_archive(base_name, format, ...)

# example:
# 将/Users/xue/Downloads/test 下的文件打包放置当前程序目录
import shutil
ret = shutil.make_archive("www", "gztar", root_dir="/Users/xue/Downloads/test")

# 将/Users/xue/Downloads/test 下的文件打包放置/Users/xue/目录
import shutil
ret = shutil.make_archive("/Users/xue/www", "gztar",root_dir="/Users/xue/Downloads/test")

shutil对压缩包的处理是调用ZipFile和TarFile两个模块来处理的,下面来详细看看这两个模块

import zipfile

# 压缩,单独一个一个压缩文件
z = zipfile.ZipFile('day5.zip', 'w')
z.write('a.log') # a.log是当前目录下的一个文件
z.write('data.data')
z.close()

# 解压
z = zipfile.ZipFile('day5.zip', 'r')
z.extractall()
z.close()
import tarfile
	
# 压缩
tar = tarfile.open('your.tar', 'w')
tar.add("/Users/xue/bbs/bbs2.zip", arcname="bbs2.zip")
tar.add("/Users/xue/bbs/cmdb.zip", arcname="cmdb.zip")
tar.close()
	
# 解压
tar = zipfile.ZipFile('day5.zip', 'r')
tar.extractall() # 可设置解压地址
tar.close()

json & pickle 模块

用于序列化的两个模块,解决了不同平台不同语言之间的数据交换,pickle相比于json,能够处理更复杂的数据类型

json: 用于字符串和puyhon数据类型进行转换
pickle: 用于python特有的类型和python的数据类型进行转换

Json模块提供了四个功能:dumps, dump, loads, load
pickle模块提供了四个功能:dumps, dump, loads, load

import pickle
	
data={'k1': 123, 'k2': 'hello'}
	
p_str = pickle.dumps(data)
print(p_str)

with open('D:/result.pk', 'w')  as fp:
	pickle.dump(data, fp)

shelve模块

是一个简单的k, v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式

import shelve
	
d = shelve.open('shelve_test') # 打开一个文件
	
class Test(object):
	def __init__(self, n):
		self.n = n
t = Test(123)
t2 = Test(123334)
	
name = ['bob', 'xue', 'rain']
# 写入
d["test"] = name # 持久化列表
d["t1"] = t # 持久化类
d["t2"] = t2
	
# 读出
d.get("test")
d.get("t")
	
d.close()

xml处理模块

xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,在json还没出来的时候,大家用的就是xml,xml格式如下:

<?xml version="1.0" encoding="utf-8" ?>
<data>
	<a name="a1">
		<to>Tove</to>
		<from updated="yes">hello</from>
		<heading>Reminder</heading>
		<body>Don't forget me this weekend!</body>
	</a>
	<a name="a2">
		<to>bbb</to>
		<from updated="yes">hello</from>
		<heading>Reminder</heading>
		<body>Don't forget me this weekend!</body>
	</a>
</data>

遍历xml、修改、删除

# Author: Mr.Xue
# 2019.10.27

import xml.etree.ElementTree as ET
	
tree = ET.parse('xmltree.xml')
root = tree.getroot()
print(root.tag)
	
## 遍历xml文档
#for child in root:
	#print(child.tag, child.attrib)
	#for i in child:
		#print(i.tag, i.text)
			
## 只遍历from节点
#for node in root.iter('from'):
	#print(node.tag, node.text)		
	
## 修改
#for node in root.iter("from"):
	#new_from = 'hello' # 字符串变量new_from
	#node.text = new_from # 赋值,修改显示信息
	#node.set("updated", 'yes') # 加了个属性
#tree.write('xmltree.xml')	
	
# 删除
for a in root.findall('a'):
	to = a.find('to').text
	if to == 'bbb':
		root.remove(a)
tree.write('xmltree2.xml')		

自己创建xml文件

# Author: Mr.Xue
# 2019.10.27

import xml.etree.ElementTree as ET
	
new_xml = ET.Element("name_list")
name = ET.SubElement(new_xml, 'name', attrib={"enrolled": 'yes'})
age = ET.SubElement(name, 'age', attrib={"checked": 'no'})
sex = ET.SubElement(name, 'sex')
age.text = '33'
	
name2 = ET.SubElement(new_xml, 'name', attrib={'enrolled': 'no'})
age = ET.SubElement(name2, 'age')
age.text = '18'
	
et = ET.ElementTree(new_xml) # 生成文档对象
et.write('test.xml', encoding='utf-8', xml_declaration=True)
	
ET.dump(new_xml) # 打印生成的格式

result:

<?xml version='1.0' encoding='utf-8'?>
<name_list>
	<name enrolled="yes">
		<age checked="no">33</age>
		<sex />
	</name>
	<name enrolled="no">
		<age>18</age>
	</name>
</name_list>

PyYAML模块

Python也可以很容易的处理ymal文档格式,只不过需要安装一个模块,参考文档:http://pyyaml.org/wiki/PyYAMLDocumentation

ConfigParser模块

用于生成和修改常见配置文档,当前模块的名称在python3.x版本中变更为configparser,常见文档格式如下:

[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
	
[bitbucket.org]
User = hg
	
[topsecret.server.com]
Port = 50022
ForwardX11 = no

怎么用python生成这样一个文件呢?

# Author: Mr.Xue
# 2019.10.27
	
import configparser
	
config = configparser.ConfigParser()
	
config["DEFAULT"] = {'ServerAliveInterval': '45',
	'Compression': 'yes',
	'CompressionLevel': '9'}
		
config['bitbucket.org'] = {}
config['bitbucket.org']['User'] = 'hg'

config['topsecret.server.com'] = {}
topsecret = config['topsecret.server.com']
topsecret['Host Port'] = '50022'
topsecret["ForwardX11"] = 'no'

config["DEFAULT"]["ForwardX11"] = 'yes'
	
with open('example.ini', 'w') as configfile:
	config.write(configfile)

读、改、删

# Author: Mr.Xue
# 2019.10.27
	
import configparser
	
conf = configparser.ConfigParser()
	
conf.read('example.ini')
	
#print(conf.sections())
#print(conf['bitbucket.org']["User"])
#print(conf.defaults())
	
# modify
sec = conf.remove_section('bitbucket.org')
conf.write(open('example.cfg', 'w'))

hashlib、hmac模块

hashlib
用于加密的相关操作,3.x里面hashlib替代了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512, MD5 算法

# Author: Mr.Xue
# 2019.10.27
	
import hashlib
	
m = hashlib.md5()
m.update(b"hello")
print(m.digest()) #2进制格式hash
print(m.hexdigest()) #16进制格式hash
m.update(b"It's me")
#m.update("萨达打".encode(encoding='utf-8'))
print(m.hexdigest())
	
m2 = hashlib.md5()
m2.update(b"helloIt's me")
print(m2.hexdigest())
	
s = hashlib.sha1()
s.update(b"helloIt's me")
print(s.hexdigest())

hmac
散列消息鉴别码,简称HMAC,是一种基于消息鉴别码MAC(Message Authentication Code)的鉴别机制。使用HMAC时,消息通讯的双方,通过验证消息中加入的鉴别密钥K来鉴别消息的真伪;它内部对我们创建 key 和 value 再进行处理然后再加密

一般用于网络通信中消息加密,前提是双方先要约定好key,就像接头暗号一样,然后消息发送把用key把消息加密,接收方用key + 消息明文再加密,拿加密后的值 跟 发送者的相对比是否相等,这样就能验证消息的真实性,及发送者的合法性了。

import hmac # 主要用于消息加密,速度比较快
#h = hmac.new(b'wueiqi') # key, value
#h.update(b'hellowo')
#h = hmac.new(b"wueiqi", b'hellowo')
h = hmac.new("天王盖地虎".encode(encoding='utf-8'), '宝塔镇河妖'.encode(encoding='utf-8'))
print(h.hexdigest())

正则表达式Re模块

常用正则表达式符号
'.'		默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行
'^'		匹配字符开头
'$'		匹配字符结尾
'*'		匹配*号前的字符0次或多次,re.findall("ab*", "cabb3abcbbac"),结果为['abb', 'ab', 'a']
'+'		匹配前一个字符1次或多次,re.findall("ab+", "ab+cd+abb+bba"),结果为['ab', 'abb']
'?'		匹配?前面的字符1次或0'{m}'	匹配前一个字符m次
'{n,m}'	匹配前一个字符n到m次,re.findall("ab{1,3}", "abbabcabbcbbb"),结果为['abb', 'ab', 'abb']
'|'		匹配|左或右的字符,re.search('abc|ABC', "ABCBabcCD").group(),结果为'ABC'
'(...)'	分组匹配,re.search("(abc){2}a(123|456)c","abcabca456c").group(),结果abcabca456c
	
'\A'	只从字符串开头匹配,如'^',re.search("\Aabc", "alexabc")是匹配不到的
'\Z'	匹配字符结尾,同'$'
'\d'	匹配数字0-9,只匹配一个
'\D'	匹配非数字
'\w'	匹配[A-Za-z0-9]
'\W'	匹配非[A-Za-z0-9]
'\s'	匹配空白字符、\t、\n、\r,re.search("\s+", "ab\tc1\n3").group() 结果为'\t'
最常用的匹配语法
re.match 从头开始匹配
re.search 匹配包含
re.findall 把所有匹配到的字符放到列表中返回
re.splitall 以匹配到的字符当做列表分隔符
re.sub 匹配字符并替换
#example:
xue@xue-MacBookAir:~$ python3
Python 3.5.2 (default, Oct  8 2019, 13:06:37) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import re
>>> re.match("^Chen", "ChenRonghua123")
<_sre.SRE_Match object; span=(0, 4), match='Chen'>
	
>>> res = re.match("^Chen", "ChenRonghua123")
>>> res.group()
'Chen'
	
>>> res = re.match("^Chen\d+", "Chen123Ronghua123")
>>> res.group()
'Chen123'
	
>>> re.search("R[a-z]+", "Chen123Ronghua123")
<_sre.SRE_Match object; span=(7, 14), match='Ronghua'>
>>> re.search("R[a-z]+", "Chen123Ronghua123Ronghua###")
<_sre.SRE_Match object; span=(7, 14), match='Ronghua'>
	
>>> re.search("a?", "alex")
<_sre.SRE_Match object; span=(0, 1), match='a'>
>>> re.search("a?", "aalex")
<_sre.SRE_Match object; span=(0, 1), match='a'>
>>> re.search("a?", "lex")
<_sre.SRE_Match object; span=(0, 0), match=''>
	
>>> re.search("[0-9]{3}", "a12l324ex")
<_sre.SRE_Match object; span=(4, 7), match='324'>
>>> re.search("[0-9]{1,3}", "a12l324ex")
<_sre.SRE_Match object; span=(1, 3), match='12'>
	
>>> re.findall("[0-9]{1,3}", "a12l324ex")
['12', '324']
	
>>> re.search("(abc){2}", "a12l324exabcabcabc")
<_sre.SRE_Match object; span=(9, 15), match='abcabc'>
>>> re.search("(abc){2}\|", "a12l324exabcabcabc|")
<_sre.SRE_Match object; span=(12, 19), match='abcabc|'>
	
>>> re.search("\A[0-9]+[a-z]\Z", "123435d")
<_sre.SRE_Match object; span=(0, 7), match='123435d'>
	
分组匹配
>>> re.search("(?P<id>[0-9]+)(?P<name>[A-Za-z]+)", "abcd1234efg567").groupdict()
{'id': '1234', 'name': 'efg'}
	
>>> re.split("[0-9]", "abc123de45gh")
['abc', '', '', 'de', '', 'gh']
>>> re.split("[0-9]+", "abc123de45gh")
['abc', 'de', 'gh']
	
>>> re.sub("[0-9]+", "|", "abc12de3f45GH")
'abc|de|f|GH'
>>> re.sub("[0-9]+", "|", "abc12de3f45GH", count=2)
'abc|de|f45GH'
	
>>> re.search(r"\\\\", r"12343\\5dd")
<_sre.SRE_Match object; span=(5, 7), match='\\\\'>
>>> re.search(r"\\", r"12343\5dd")
<_sre.SRE_Match object; span=(5, 6), match='\\'>

匹配模式:

re.I(re.IGNORECASE): 忽略大小写
re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
M(MULTILINE): 多行模式,改变'^''$'的行为(参见上图)
S(DOTALL): 点任意匹配模式,改变'.'的行为

>>> re.search("[a-z]+", "abcdE", flags=re.I)
<_sre.SRE_Match object; span=(0, 5), match='abcdE'>

logging模块

参考:
https://www.cnblogs.com/alex3714/articles/5161349.html

paramiko模块

该模块基于SSH用于连接远程服务器并执行相关操作

SSHClient
用于连接远程服务器并执行基本命令

基于用户名密码连接:

import paramiko
  
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='c1.salt.com', port=22, username='root', password='123')
  
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
res, err = stdout.read(), stderr.read()
s = res if res else err
print(s)
  
# 关闭连接
ssh.close()
# SSHClient 封装 Transport

import paramiko

transport = paramiko.Transport(('hostname', 22))
transport.connect(username='root', password='123')

ssh = paramiko.SSHClient()
ssh._transport = transport

stdin, stdout, stderr = ssh.exec_command('df')
print stdout.read()

transport.close()

基于公钥密钥连接:

import paramiko
 
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
 
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='c1.salt.com', port=22, username='root', pkey=private_key)
 
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read()
 
# 关闭连接
ssh.close()
# SSHClient 封装 Transport

import paramiko

private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')

transport = paramiko.Transport(('hostname', 22))
transport.connect(username='root', pkey=private_key)

ssh = paramiko.SSHClient()
ssh._transport = transport

stdin, stdout, stderr = ssh.exec_command('df')

transport.close()
#基于私钥字符串进行连接

import paramiko
from io import StringIO

key_str = """-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAq7gLsqYArAFco02/55IgNg0r7NXOtEM3qXpb/dabJ5Uyky/8
NEHhFiQ7deHIRIuTW5Zb0kD6h6EBbVlUMBmwJrC2oSzySLU1w+ZNfH0PE6W6fans
H80whhuc/YgP+fjiO+VR/gFcqib8Rll5UfYzf5H8uuOnDeIXGCVgyHQSmt8if1+e
7hn1MVO1Lrm9Fco8ABI7dyv8/ZEwoSfh2C9rGYgA58LT1FkBRkOePbHD43xNfAYC
tfLvz6LErMnwdOW4sNMEWWAWv1fsTB35PAm5CazfKzmam9n5IQXhmUNcNvmaZtvP
c4f4g59mdsaWNtNaY96UjOfx83Om86gmdkKcnwIDAQABAoIBAQCnDBGFJuv8aA7A
ZkBLe+GN815JtOyye7lIS1n2I7En3oImoUWNaJEYwwJ8+LmjxMwDCtAkR0XwbvY+
c+nsKPEtkjb3sAu6I148RmwWsGncSRqUaJrljOypaW9dS+GO4Ujjz3/lw1lrxSUh
IqVc0E7kyRW8kP3QCaNBwArYteHreZFFp6XmtKMtXaEA3saJYILxaaXlYkoRi4k8
S2/K8aw3ZMR4tDCOfB4o47JaeiA/e185RK3A+mLn9xTDhTdZqTQpv17/YRPcgmwz
zu30fhVXQT/SuI0sO+bzCO4YGoEwoBX718AWhdLJFoFq1B7k2ZEzXTAtjEXQEWm6
01ndU/jhAasdfasdasdfasdfa3eraszxqwefasdfadasdffsFIfAsjQb4HdkmHuC
OeJrJOd+CYvdEeqJJNnF6AbHyYHIECkj0Qq1kEfLOEsqzd5nDbtkKBte6M1trbjl
HtJ2Yb8w6o/q/6Sbj7wf/cW3LIYEdeVCjScozVcQ9R83ea05J+QOAr4nAoGBAMaq
UzLJfLNWZ5Qosmir2oHStFlZpxspax/ln7DlWLW4wPB4YJalSVovF2Buo8hr8X65
lnPiE41M+G0Z7icEXiFyDBFDCtzx0x/RmaBokLathrFtI81UCx4gQPLaSVNMlvQA
539GsubSrO4LpHRNGg/weZ6EqQOXvHvkUkm2bDDJAoGATytFNxen6GtC0ZT3SRQM
WYfasdf3xbtuykmnluiofasd2sfmjnljkt7khghmghdasSDFGQfgaFoKfaawoYeH
C2XasVUsVviBn8kPSLSVBPX4JUfQmA6h8HsajeVahxN1U9e0nYJ0sYDQFUMTS2t8
RT57+WK/0ONwTWHdu+KnaJECgYEAid/ta8LQC3p82iNAZkpWlGDSD2yb/8rH8NQg
9tjEryFwrbMtfX9qn+8srx06B796U3OjifstjJQNmVI0qNlsJpQK8fPwVxRxbJS/
pMbNICrf3sUa4sZgDOFfkeuSlgACh4cVIozDXlR59Z8Y3CoiW0uObEgvMDIfenAj
98pl3ZkCgYEAj/UCSni0dwX4pnKNPm6LUgiS7QvIgM3H9piyt8aipQuzBi5LUKWw
DlQC4Zb73nHgdREtQYYXTu7p27Bl0Gizz1sW2eSgxFU8eTh+ucfVwOXKAXKU5SeI
+MbuBfUYQ4if2N/BXn47+/ecf3A4KgB37Le5SbLDddwCNxGlBzbpBa0=
-----END RSA PRIVATE KEY-----"""

private_key = paramiko.RSAKey(file_obj=StringIO(key_str))
transport = paramiko.Transport(('10.0.1.40', 22))
transport.connect(username='root', pkey=private_key)

ssh = paramiko.SSHClient()
ssh._transport = transport

stdin, stdout, stderr = ssh.exec_command('df')
result = stdout.read()

transport.close()

print(result)

SFTPClient

用于连接远程服务器并执行上传下载

基于用户名密码上传下载

import paramiko
 
transport = paramiko.Transport(('hostname',22))
transport.connect(username='root',password='123')
 
sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put('/tmp/location.py', '/tmp/test.py')
# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')
 
transport.close()

基于公钥密钥上传下载

import paramiko
 
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
 
transport = paramiko.Transport(('hostname', 22))
transport.connect(username='root', pkey=private_key )
 
sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put('/tmp/location.py', '/tmp/test.py')
# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')
 
transport.close()

补充

RSA:非对称密钥验证

  • 公钥
  • 私钥

比如说:
10.0.0.31请求去连接10.0.0.41,那么
私钥放在31,公钥放在41

需要先在31上生成钥匙对,用命令ssh-keygen,默认保存在当前用户的家目录下

用more /root/.ssh/id_rsa.pub查看公钥,拷贝到41去,用vim .ssh/authorized_keys打开需要粘贴的位置
除了这个方法,还可以用以下命令来拷贝公钥,ssh-copy-id “-p52113 [email protected]

ssh [email protected] -p53112这条命令是Linux中远程登录另一台机器的命令

rwx rwx rwx
421
属主属组属others
可读可写可执行

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章