python-常用模块

一、difflib模块
文件差异对比模块
1.比较两个文件的不同.

import difflib

def read_content(filename):
    with open(filename) as f:
        return f.read()

content1 = read_content('dir/httpd.conf').splitlines()
content2 = read_content('dir/httpd_backup.conf').splitlines()

# 实例化对象
d = difflib.Differ()

res = list(d.compare(content1,content2))

from pprint import pprint as _pprint
print(_pprint(res))
print(''.join(res),end='')

2.以html页面显示两个文件的不同

import difflib
import sys

def read_content(filename):
    with open(filename) as f:
        return f.read()
def main():
    if len(sys.argv) !=4:
        print("""
Usage:
        %s 配置文件名1  配置文件名2  html文件名
        """%(sys.argv[0]))
    else:
        file1 = sys.argv[1]
        file2 = sys.argv[2]
        htmlFileName = sys.argv[3]

        content1 = read_content(file1).splitlines()
        content2 = read_content(file2).splitlines()

        d = difflib.HtmlDiff()

        html_content= d.make_file(content1,content2)

        with open(htmlFileName,'w') as f:
            f.write(html_content)

        print("写入%s成功" %(htmlFileName))

if __name__ == "__main__":
    main()

二、OS模块
os

os.environ  一个dictionary 包含环境变量的映射关系 
os.name     显示当前使用的平台
os.sep      显示当前平台下路径分隔符
os.linesep  给出当前平台使用的行终止符
os.remove('filename')       删除一个文件
os.rename("oldname","newname")      重命名文件
os.getcwd()     显示当前python脚本工作路径
os.chdir(dir)       改变当前目录,注意windows下用到转义
os.listdir('dirname')       返回指定目录下的所有文件和目录名
os.makedirs('dirname/dirname')      可生成多层递规目录
os.rmdir('dirname')     删除单级目录
os.getlogin()       得到用户登录名称
os.getenv(‘key’)    得到环境变量配置
os.putenv(‘key’)    设置环境变量
os.system()     运行shell命令,注意:这里是打开一个新的shell,运行命令,当命令结束后,关闭shell。
import os

print(os.environ)

print(os.access('/etc/passwd',os.R_OK))
print(os.access('/etc/passwd',os.W_OK))
print(os.access('/etc/passwd',os.X_OK))

filestat = os.stat('/etc/passwd')   ## 文件状态
print(filestat,'\n',
      type(filestat))
print(filestat.st_blocks)
print(filestat.st_gid)
print(filestat.st_uid)
print(filestat.st_mode)
print(filestat.st_ctime)


/usr/local/python3/bin/python3.6 /root/PycharmProjects/day12/01_常用模块.py
environ({'PATH': '/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/home/kiosk/.local/bin:/home/kiosk/bin', 'XAUTHORITY': '/root/.xauthSzTEJE', 'LC_MEASUREMENT': 'zh_CN.UTF-8', 'IMSETTINGS_MODULE': 'none', 'HISTCONTROL': 'ignoredups', 'XMODIFIERS': '@im=ibus', 'GDMSESSION': 'gnome-classic', 'LC_TIME': 'zh_CN.UTF-8', 'DBUS_SESSION_BUS_ADDRESS': 'unix:abstract=/tmp/dbus-BakeaW5IfG,guid=ee50c8c0688448752fe814095b20fce1', 'XDG_CURRENT_DESKTOP': 'GNOME-Classic:GNOME', 'MAIL': '/var/spool/mail/kiosk', 'SSH_AGENT_PID': '2700', 'LD_LIBRARY_PATH': '/opt/pycharm-community-2017.1.4/bin:', 'SESSION_MANAGER': 'local/unix:@/tmp/.ICE-unix/2493,unix/unix:/tmp/.ICE-unix/2493', 'USERNAME': 'kiosk', 'LC_PAPER': 'zh_CN.UTF-8', 'LOGNAME': 'kiosk', 'PWD': '/root/PycharmProjects/day12', 'PYCHARM_HOSTED': '1', 'WINDOWID': '35651591', 'PYTHONPATH': '/root/PycharmProjects/day07:/root/PycharmProjects', 'LESSOPEN': '||/usr/bin/lesspipe.sh %s', 'SHELL': '/bin/bash', 'QT_GRAPHICSSYSTEM_CHECKED': '1', 'QTINC': '/usr/lib64/qt-3.3/include', 'GNOME_DESKTOP_SESSION_ID': 'this-is-deprecated', 'IMSETTINGS_INTEGRATE_DESKTOP': 'yes', 'XDG_SESSION_DESKTOP': 'gnome-classic', 'LS_COLORS': 'rs=0:di=38;5;27:ln=38;5;51:mh=44;38;5;15:pi=40;38;5;11:so=38;5;13:do=38;5;5:bd=48;5;232;38;5;11:cd=48;5;232;38;5;3:or=48;5;232;38;5;9:mi=05;48;5;232;38;5;15:su=48;5;196;38;5;15:sg=48;5;11;38;5;16:ca=48;5;196;38;5;226:tw=48;5;10;38;5;16:ow=48;5;10;38;5;21:st=48;5;21;38;5;15:ex=38;5;34:*.tar=38;5;9:*.tgz=38;5;9:*.arc=38;5;9:*.arj=38;5;9:*.taz=38;5;9:*.lha=38;5;9:*.lz4=38;5;9:*.lzh=38;5;9:*.lzma=38;5;9:*.tlz=38;5;9:*.txz=38;5;9:*.tzo=38;5;9:*.t7z=38;5;9:*.zip=38;5;9:*.z=38;5;9:*.Z=38;5;9:*.dz=38;5;9:*.gz=38;5;9:*.lrz=38;5;9:*.lz=38;5;9:*.lzo=38;5;9:*.xz=38;5;9:*.bz2=38;5;9:*.bz=38;5;9:*.tbz=38;5;9:*.tbz2=38;5;9:*.tz=38;5;9:*.deb=38;5;9:*.rpm=38;5;9:*.jar=38;5;9:*.war=38;5;9:*.ear=38;5;9:*.sar=38;5;9:*.rar=38;5;9:*.alz=38;5;9:*.ace=38;5;9:*.zoo=38;5;9:*.cpio=38;5;9:*.7z=38;5;9:*.rz=38;5;9:*.cab=38;5;9:*.jpg=38;5;13:*.jpeg=38;5;13:*.gif=38;5;13:*.bmp=38;5;13:*.pbm=38;5;13:*.pgm=38;5;13:*.ppm=38;5;13:*.tga=38;5;13:*.xbm=38;5;13:*.xpm=38;5;13:*.tif=38;5;13:*.tiff=38;5;13:*.png=38;5;13:*.svg=38;5;13:*.svgz=38;5;13:*.mng=38;5;13:*.pcx=38;5;13:*.mov=38;5;13:*.mpg=38;5;13:*.mpeg=38;5;13:*.m2v=38;5;13:*.mkv=38;5;13:*.webm=38;5;13:*.ogm=38;5;13:*.mp4=38;5;13:*.m4v=38;5;13:*.mp4v=38;5;13:*.vob=38;5;13:*.qt=38;5;13:*.nuv=38;5;13:*.wmv=38;5;13:*.asf=38;5;13:*.rm=38;5;13:*.rmvb=38;5;13:*.flc=38;5;13:*.avi=38;5;13:*.fli=38;5;13:*.flv=38;5;13:*.gl=38;5;13:*.dl=38;5;13:*.xcf=38;5;13:*.xwd=38;5;13:*.yuv=38;5;13:*.cgm=38;5;13:*.emf=38;5;13:*.axv=38;5;13:*.anx=38;5;13:*.ogv=38;5;13:*.ogx=38;5;13:*.aac=38;5;45:*.au=38;5;45:*.flac=38;5;45:*.mid=38;5;45:*.midi=38;5;45:*.mka=38;5;45:*.mp3=38;5;45:*.mpc=38;5;45:*.ogg=38;5;45:*.ra=38;5;45:*.wav=38;5;45:*.axa=38;5;45:*.oga=38;5;45:*.spx=38;5;45:*.xspf=38;5;45:', 'SHLVL': '4', 'QT_PLUGIN_PATH': '/usr/lib64/kde4/plugins:/usr/lib/kde4/plugins', 'LC_MONETARY': 'zh_CN.UTF-8', 'QT_IM_MODULE': 'ibus', 'HISTSIZE': '1000', 'TERM': 'xterm-256color', 'XFILESEARCHPATH': '/usr/dt/app-defaults/%L/Dt', 'LANG': 'en_GB.utf8', 'XDG_SESSION_ID': '1', 'DISPLAY': ':0', '_': '/opt/pycharm-community-2017.1.4/jre64/bin/java', 'GDM_LANG': 'en_GB.utf8', 'PYTHONIOENCODING': 'UTF-8', 'DESKTOP_SESSION': 'gnome-classic', 'GPG_AGENT_INFO': '/run/user/1001/keyring/gpg:0:1', 'USER': 'kiosk', 'XDG_MENU_PREFIX': 'gnome-', 'WINDOWPATH': '1', 'VTE_VERSION': '3803', 'LC_NUMERIC': 'zh_CN.UTF-8', 'XDG_SEAT': 'seat0', 'SSH_AUTH_SOCK': '/run/user/1001/keyring/ssh', 'PYTHONUNBUFFERED': '1', 'HOSTNAME': 'foundation10.example.com', 'QTDIR': '/usr/lib64/qt-3.3', 'NLSPATH': '/usr/dt/lib/nls/msg/%L/%N.cat', 'GNOME_SHELL_SESSION_MODE': 'classic', 'KDEDIRS': '/usr', 'XDG_RUNTIME_DIR': '/run/user/1001', 'XDG_VTNR': '1', 'QTLIB': '/usr/lib64/qt-3.3/lib', 'HOME': '/root'})
True
True
False
os.stat_result(st_mode=33188, st_ino=138422790, st_dev=64768, st_nlink=1, st_uid=0, st_gid=0, st_size=3342, st_atime=1528888501, st_mtime=1523758264, st_ctime=1523758264) 
 'os.stat_result'>
8
0
0
33188
1523758264.3586972

os.path

os.path.abspath()   获取绝对路径os.path.abspath("1.txt") == os.path.join(os.getcwd(),"1.txt")
os.path.split()     用于分开一个目录名称中的目录部分和文件名称部分
os.pardir       表示当前平台下上一级目录的字符
os.path.join(path, name)    连接目录和文件名。
os.path.basename(path)      返回文件名
os.path.dirname(path)       返回文件路径
os.path.getctime("/root/1.txt")     返回1.txt的ctime(创建时间)时间戳
os.path.exists(os.getcwd())     判断文件是否存在
os.path.isfile(os.getcwd())     判断是否是文件名,10os.path.isdir('c:\Python\temp')     判断是否是目录,10os.path.islink('/home/111.sql')     是否是符号连接,windows下不可用
os.path.ismout(os.getcwd())     是否是文件系统安装点,windows下不可用
os.path.samefile(os.getcwd(), '/home')      看看两个文件名是不是指的是同一个文件
os.walk()   能够把给定的目录下的所有目录和文件遍历出来
os.path.walk('/home/huaying', test_fun, "a.c")      遍历/home/huaying下所有子目录包括本目录,对于每个目录都会调用函数test_fun。
print(os.path.getsize('/etc/passwd'))
print(os.path.getmtime('/etc/passwd'))

/usr/local/python3/bin/python3.6 /root/PycharmProjects/day12/01_常用模块.py
3342
1523758264.3356972

三、sys模块

dir(sys)    dir()方法查看模块中可用的方法。注意:如果是在编辑器,一定要注意要事先声明代码的编码方式,否则中文会乱码。
sys.argv    实现从程序外部向程序传递参数
sys.exit([arg])     程序中间的退出,arg=0为正常退出
sys.getdefaultencoding()    获取系统当前编码,一般默认为ascii
sys.setdefaultencoding()    设置系统默认编码,执行dir(sys)时不会看到这个方法,在解释器中执行不通过,可以先执行reload(sys), 再执行setdefaultencoding('utf8'),将系统编码设置为utf8
sys.getfilesystemencoding() 获取文件系统编码方式,Windows下返回'mbcs'mac下返回'utf-8'
sys.path    获取指定模块搜索路径的字符串集合,可以将写好的模块放在得到的某个路径下,就可以在程序中import时正确找到
sys.platform    获取当前系统平台
sys.stdinsys.stdoutsys.stderr     stdinstdout,以及stderr变量包含与标准I/O流对应的流对象。如果需要更好地控制输出,而print不能满足要求,它们就是你所需要的。你也可以替换它们,重定向输出和输入到其它设备(device),或者以非标准的方式处理它们。
sys.modules     是一个全局字典,该字典是python启动后就加载在内存中。每当程序员导入新的模块,sys.modules将自动记录该模块。当第二次再导入该模块时,python会直接到字典中查找,从而加快程序运行的速度。它拥有字典所拥有的一切方法。
import sys

print(sys.version,type(sys.version))
print(sys.version_info)
version = sys.version_info
print(str(version.major) + '.' + str(version.minor))
print(sys.platform)
print('this is a error',sys.stderr)
print('this is a error',sys.stdin)
print('this is a error',sys.stdout)


/usr/local/python3/bin/python3.6 /root/PycharmProjects/day12/01_常用模块.py
3.6.4 (default, Jun  1 2018, 18:57:40) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] <class 'str'>
sys.version_info(major=3, minor=6, micro=4, releaselevel='final', serial=0)
3.6
linux
this is a error <_io.TextIOWrapper name='' mode='w' encoding='UTF-8'>
this is a error <_io.TextIOWrapper name='' mode='r' encoding='UTF-8'>
this is a error <_io.TextIOWrapper name='' mode='w' encoding='UTF-8'>

四、Time模块

在Python中,与时间处理有关的模块就包括:time,datetime以及calendar

1.在Python中,通常有这几种方式来表示时间:1)时间戳 2)格式化的时间字符串 3)元组(struct_time)共九个元素。由于Python的time模块实现主要调用C库,所以各个平台可能有所不同。

2.UTC(Coordinated Universal Time,世界协调时)亦即格林威治天文时间,世界标准时间。在中国为UTC+8。DST(Daylight Saving Time)即夏令时。

3.时间戳(timestamp)的方式:通常来说,时间戳表示的是从19701100:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。返回时间戳方式的函数主要有time(),clock()等。

4.元组(struct_time)方式:struct_time元组共有9个元素,返回struct_time的函数主要有gmtime(),localtime(),strptime()。下面列出这种方式元组中的几个元素:

元组(struct_time)方式中的几个元素:
python-常用模块_第1张图片
time模块中常用的几个函数:

## 导入time模块
1time.localtime([secs]):将一个时间戳转换为当前时区的struct_time。secs参数未提供,则以当前时间为准。

print(time.localtime())
time.struct_time(tm_year=2018, tm_mon=6, tm_mday=14, tm_hour=10, tm_min=42, tm_sec=29, tm_wday=3, tm_yday=165, tm_isdst=0)

2time.gmtime([secs]):和localtime()方法类似,gmtime()方法是将一个时间戳转换为UTC时区(0时区)的struct_time。
## 注意:这里的tm_wday=3表示的是周几,但是要在这个返回值的基础上往后推一天,即表示的是周四,而不是周三

print(time.gmtime())
time.struct_time(tm_year=2018, tm_mon=6, tm_mday=14, tm_hour=2, tm_min=44, tm_sec=41, tm_wday=3, tm_yday=165, tm_isdst=0)

3time.time():返回当前时间的时间戳。

print(time.time())
1528944281.1089418

4time.mktime(t):将一个struct_time转化为时间戳。

print(time.mktime(time.localtime()))
1528944559.0

5time.sleep(secs):线程推迟指定的时间运行。单位为秒。

6time.clock():这个需要注意,在不同的系统上含义不同。在UNIX系统上,它返回的是“进程时间”,它是用秒表示的浮点数(时间戳)。
 而在WINDOWS中,第一次调用,返回的是进程运行的实际时间。而第二次之后的调用是自第一次调用以后到现在的运行时间。(实际上是以WIN32上QueryPerformanceCounter()为基础,它比毫秒表示更为精确)

if __name__ == '__main__':
    time.sleep(1)
    print("clock1:%s" %(time.clock()))
    time.sleep(1)
    print("clock1:%s" %(time.clock()))
    time.sleep(1)
    print("clock1:%s" %(time.clock()))

/usr/local/python3/bin/python3.6 /home/kiosk/PycharmProjects/day_08/01_time.py
clock1:3.35238137808e-006 
clock2:1.00004944763 
clock3:2.00012040636
## 其中第一个clock()输出的是程序运行时间
## 第二、三个clock()输出的都是与第一个clock的时间间隔

7time.asctime([t]):把一个表示时间的元组或者struct_time表示为这种形式:'Sun Jun 20 23:21:05 1993'。如果没有参数,将会将time.localtime()作为参数传入。

print(time.asctime())

Thu Jun 14 11:05:47 2018

8time.ctime([secs]):把一个时间戳(按秒计算的浮点数)转化为time.asctime()的形式。如果参数未给或者为None的时候,将会默认time.time()为参数。它的作用相当于time.asctime(time.localtime(secs))。

print(time.ctime())
print(time.ctime(time.time()))

Thu Jun 14 11:08:59 2018
Thu Jun 14 11:08:59 2018

9time.strftime(format[, t]):把一个代表时间的元组或者struct_time(如由time.localtime()和time.gmtime()返回)转化为格式化的时间字符串。如果t未指定,将传入time.localtime()。如果元组中任何一个元素越界,ValueError的错误将会被抛出。

print(time.strftime("%Y-%m-%d %X",time.localtime()))
2018-06-14 11:11:23

10time.strptime(string[, format]):把一个格式化时间字符串转化为struct_time。实际上它和strftime()是逆操作。

s = '2018-6-18'
print(time.strptime(s,'%Y-%m-%d'))

time.struct_time(tm_year=2018, tm_mon=6, tm_mday=18, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=0, tm_yday=169, tm_isdst=-1)

python-常用模块_第2张图片
python-常用模块_第3张图片

# 4. 获取指定文件创建时间;
atime = os.path.getatime('/etc/passwd')
# 把看不懂的时间戳转化为字符串格式;
print(time.ctime(atime))

# 把看不懂的时间戳转化为元组格式
print(time.localtime(atime))


# 将元组格式转化为时间戳格式
tuple_time = time.localtime()
print(time.mktime(tuple_time))



# 将元组格式转化为字符串显示
print(time.strftime('%D'))
print(time.strftime('%D', tuple_time))
print(time.strftime('%Y-%m-%d', tuple_time))
print(time.strftime('%F', tuple_time))
print(time.strftime('%T', tuple_time))


# 将字符串格式转化为元组
s = '2008-10-30'
print(time.strptime(s, '%Y-%m-%d'))
print(time.strptime("12:00:40", '%H:%M:%S'))

五、DateTime模块

import os
from datetime import date,time,datetime,timedelta

# 1. date
# 显示当前的日期;
today = date.today()
print(today)
2018-06-15

# 转化为其他字符串格式
print(today.strftime('%m/%d/%Y'))
06/15/2018

# 转化为元组格式便于解析
print(today.timetuple())
time.struct_time(tm_year=2018, tm_mon=6, tm_mday=15, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=4, tm_yday=166, tm_isdst=-1)

# 替换年月日;
print(today.replace(day=30))
print(today.replace(year=2050))
print(today.replace(month=8))
2018-06-30
2050-06-15
2018-08-15

# 转化时间戳为date对象;
atime = os.path.getmtime('/etc/passwd')
d = date.fromtimestamp(atime)
print(d,type(d))
2018-04-15 'datetime.date'>

# 2.time

t = time(10,20,45)
print(t.strftime("%H:%M"))
print(t.replace(hour=11))
print(t.replace(minute=30))
print(t.replace(second=59))

10:20
11:20:45
10:30:45
10:20:59

# 3. datetime
today = date.today()
d1 = datetime.today()
print(d1)
2018-06-15 10:18:30.961094

# 4. delta (只对day)
d2 = datetime.today()
print(d2)
yesterday = d2 - timedelta(days=1)  ## 时间向前推一天
print(yesterday.strftime('%Y-%m-%d'))

2018-06-15 10:21:20.704758
2018-06-14

六、shutil模块

shutil 是高级的文件,文件夹,压缩包处理模块。

1.应用

import 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)

shutil.copyfileobj(open('old.xml','r'),open('new.xml','w'))

# 拷贝文件
shutil.copyfile(src, dst)

shutil.copyfile('f1.log','f2.log')

#  仅拷贝权限。内容、组、用户均不变
shutil.copymode(src, dst)

shutil.copymode('f1.log', 'f2.log')

#  仅拷贝状态的信息,包括:mode bits, atime, mtime, flags
shutil.copystat(src, dst)

shutil.copystat('f1.log', 'f2.log')

# 拷贝文件和权限
shutil.copy(src, dst)

shutil.copy('f1.log', 'f2.log')

#  拷贝文件和状态信息
shutil.copy2(src, dst)

shutil.copy2('f1.log', 'f2.log')

# 递归的去拷贝文件夹
 shutil.copytree('/var/log', '/mnt/log', ignore=shutil.ignore_patterns('*.log'))  拷贝文件时忽略以log结尾的文件
 shutil.copytree('f1', 'f2', symlinks=True, ignore=shutil.ignore_patterns('*.log'))

# 递归的去删除文件
shutil.rmtree(path[, ignore_errors[, onerror]])

shutil.rmtree('f1')

#  递归的去移动文件,它类似mv命令,其实就是重命名。
shutil.move(src, dst)

shutil.move('folder1', 'folder3')

# 创建压缩包并返回文件路径,例如:zip、tar
shutil.make_archive(base_name, format,...)

    base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
    如:www                        =>保存至当前路径
    如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/
    format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
    root_dir: 要压缩的文件夹路径(默认当前目录)
    owner: 用户,默认当前用户
    group: 组,默认当前组
    logger: 用于记录日志,通常是logging.Logger对象

shutil.make_archive('/etc/passwd', "gztar", '/mnt/')

七、Socket模块

套接字是为特定网络协议(例如TCP/IP,ICMP/IP,UDP/IP等)套件对上的网络应用程序提供者提供当前可移植标准的对象。它们允许程序接受并进行连接,如发送和接受数据。为了建立通信通道,网络通信的每个端点拥有一个套接字对象极为重要。和大多数语言一样,Python 支持面向连接和无连接,实现接口功能与步骤也大致相同。
1)面向连接即需要先连接然后通讯, 面向连接主要协议就是传输控制协议(tcp),要创建tcp套接字时需要指定套接字类型为 SOCK_STRAM,表达了他作为流套接字的特点。
2)无连接,顾名思义无需建立连接就可以进行通讯,这时数据到达顺序、可靠性就无法保证了。实现这种连接的协议就是用户数据包协议(udp)。创建UDP时需要指定套接字类型为 SOCK_DGRAM。

在使用的时候,每个socket都被绑定到一个特定的IP地址和端口。IP地址是一个由4个数组成的序列,这4个数均是范围 0~255中的值(例如,220,176,36,76);端口数值的取值范围是0~65535。端口数小于1024的都是为众所周知的网络服务所保留的(例如Web服务使用的80端口);最大的保留数被存储在socket模块的IPPORT_RESERVED变量中。你也可以为你的程序使用另外的端口数值。
地址127.0.0.1是本机地址;它始终指向当前的计算机。

模拟ssh服务(执行命令)

TCP服务器端:

# 1. 第一步是创建socket对象。调用socket构造函数。如:
socket = socket.socket( family, type )
family参数代表地址家族,可为AF_INET或AF_UNIX。AF_INET家族包括Internet地址,AF_UNIX家族用于同一台机器上的进程间通信。type参数代表套接字类型,可为SOCK_STREAM(流套接字)和SOCK_DGRAM(数据报套接字)

# 2. 第二步是将socket绑定到指定地址。这是通过socket对象的bind方法来实现的:
socket.bind( address )
由AF_INET所创建的套接字,address地址必须是一个双元素元组,格式是(host,port)。host代表主机,port代表端口号。如果端口号正在使用、主机名不正确或端口已被保留,bind方法将引发socket.error异常。

# 3. 第三步是使用socket套接字的listen方法接收连接请求。
socket.listen( backlog )
backlog指定最多允许多少个客户连接到服务器。它的值至少为1。收到连接请求后,这些请求需要排队,如果队列满,就拒绝请求

# 4. 第四步是服务器套接字通过socket的accept方法等待客户请求一个连接。
connection, address = socket.accept()
调 用accept方法时,socket会时入“waiting”状态。客户请求连接时,方法建立连接并返回服务器。accept方法返回一个含有两个元素的 元组(connection,address)。第一个元素connection是新的socket对象,服务器必须通过它与客户通信;第二个元素 address是客户的Internet地址。

# 5. 第五步是处理阶段,服务器和客户端通过send和recv方法通信(传输 数据)。服务器调用send,并采用字符串形式向客户发送信息。send方法返回已发送的字符个数。服务器使用recv方法从客户接收信息。调用recv 时,服务器必须指定一个整数,它对应于可通过本次方法调用来接收的最大数据量。recv方法在接收数据时会进入“blocked”状态,最后返回一个字符 串,用它表示收到的数据。如果发送的数据量超过了recv所允许的,数据会被截短。多余的数据将缓冲于接收端。以后调用recv时,多余的数据会从缓冲区 删除(以及自上次调用recv以来,客户可能发送的其它任何数据)。

# 6. 传输结束,服务器调用socket的close方法关闭连接
import os
import socket

HOST = '172.25.254.1'
PORT = 6666
ConnectCount = 5
MaxByte = 1024*8

# 1. server端程序, 创建socket对象
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 2. 绑定ip和端口
serverSocket.bind((HOST, PORT))

# 3. 监听是否有客户端连接;这里的ConnectCount代表最多只允许几个客户端连接;
serverSocket.listen(ConnectCount)

print("Server is starting.......")

# 4. 如果有客户端连接, 则接收客户端连接, 返回2个值, 一个是客户端的socket对象;
# 另外一个是客户端连接服务端的ip和端口
clientSocket, address = serverSocket.accept()

while True:
    # 5. 接收客户端的消息;MaxByte代表每次最多接收的字节数;
    cmd = clientSocket.recv(MaxByte).decode('utf-8')
    print("接收到客户端的消息:", cmd)


    # 判断命令是否执行成功?
    if os.system(cmd) == 0:
        # 6. 给客户端一个响应, 回复消息;
        cmd_res = os.popen(cmd).read()
    else:
        cmd_res = "%s命令找不到" %(cmd)

    # encode, 并且发送消息
    cmd_res = cmd_res.encode('utf-8')
    clientSocket.send(cmd_res)

# 7. 关闭socket对象
serverSocket.close()
/usr/local/python3/bin/python3.6 /root/PycharmProjects/day13/01_socket-server.py
Server is starting......
sh: $'\344\275\240\346\230\257\357\274\237': command not found
接收到客户端的消息: 你是?
接收到客户端的消息: ls
01_socket-server.py
02_socket-client.py
接收到客户端的消息: df
Filesystem            1K-blocks     Used Available Use% Mounted on
/dev/mapper/rhel-root  45021720 27952324  17069396  63% /
devtmpfs                1923876        0   1923876   0% /dev
tmpfs                   1940748      148   1940600   1% /dev/shm
tmpfs                   1940748   187216   1753532  10% /run
tmpfs                   1940748        0   1940748   0% /sys/fs/cgroup
/dev/mapper/rhel-home  21980688 15786540   6194148  72% /home
/dev/sda7                508588   167912    340676  34% /boot
tmpfs                    388152       28    388124   1% /run/user/1001

TCP客户端:

# 1. 第一步是创建一个socket以连接服务器:socket = socket.socket( family, type )

# 2. 第二步是使用socket的connect方法连接服务器。对于AF_INET家族,连接格式如下:socket.connect( (host,port) )host代表服务器主机名或IP,port代表服务器进程所绑定的端口号。如连接成功,客户就可通过套接字与服务器通信,如果连接失败,会引发socket.error异常。

# 3. 第三步是处理阶段,客户和服务器将通过send方法和recv方法通信。

# 4. 传输结束,客户通过调用socket的close方法关闭连接。
import socket

host = '172.25.254.1'
port = 6666

# 1. 创建socket;
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 2. 连接远程主机
clientSocket.connect((host, port))
mysock = clientSocket.getsockname()
print("连接{0}的socket为{1}".format(host, mysock))


while True:
    cmd = input("client>>:").encode('utf-8')
    # 3.给server主机发送消息;
    clientSocket.send(cmd)
    # 4. 接收服务端返回的消息;
    reply = clientSocket.recv(1024*8).decode('utf-8')
    print("接收到服务端的消息:", reply)

# 5. 关闭socket对象
clientSocket.close()
连接172.25.254.10socket为('172.25.254.10', 33889)
client>>你是?
接收到服务端的消息 你是?命令找不到
client>>ls
接收到服务端的消息 01_socket-server.py
02_socket-client.py

client>>df
接收到服务端的消息 Filesystem            1K-blocks     Used Available Use% Mounted on
/dev/mapper/rhel-root  45021720 27952324  17069396  63% /
devtmpfs                1923876        0   1923876   0% /dev
tmpfs                   1940748      148   1940600   1% /dev/shm
tmpfs                   1940748   187216   1753532  10% /run
tmpfs                   1940748        0   1940748   0% /sys/fs/cgroup
/dev/mapper/rhel-home  21980688 15786540   6194148  72% /home
/dev/sda7                508588   167912    340676  34% /boot
tmpfs                    388152       28    388124   1% /run/user/1001

client>>

paramiko模块

paramiko基于ssh用于连接远程服务器, 执行命令, 上传和下载;

1.基于用户名和密码远程连接, 执行命令;

# 1. 创建SSH对象;
ssh = paramiko.SSHClient()

# 2. 如果ip之前不在know_host里面, 自动解决yes/no的问题;
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# 3. 连接服务器
ssh.connect(hostname='172.25.254.1', port=22, username='root', password='redhat')

#4. 远程执行命令 (stdin:标准输入  stdout:标准输出  stderr:标准错误)
stdin, stdout, stderr = ssh.exec_command('hostname')


# 5. 获取命令结果;
result = stdout.read()
print(result)

# 6. 关闭ssh连接
ssh.close()


/usr/local/python3/bin/python3.6 /root/PycharmProjects/day13/03_paramiko.py
b'foundation10.example.com\n'

2.基于用户名和密码远程连接, 上传和下载文件;(SFTPClient)

transport = paramiko.Transport(('172.25.254.1', 22))
transport.connect(username='root', password='redhat')

sftp = paramiko.SFTPClient.from_transport(transport)

# 将本机的文件上传到远程服务器上;
sftp.put('/etc/passwd', '/tmp/westos89')

# 下载远程主机的文件到local;
sftp.get('/tmp/westos89', '/tmp/qq')

sftp.close()
[root@localhost tmp]# ll /tmp/westos 
-rw-r--r--. 1 root root 3342 615 04:17 /tmp/westos
[root@localhost tmp]# logout
Connection to 172.25.254.1 closed.
[kiosk@foundation10 tmp]$ ll /tmp/qq
-rw-r--r-- 1 root root 3342 615 16:17 /tmp/qq

3.基于paramiko的主机批量管理工具
需求:
1. 主机分组;对选中的主机进行批量操作;
2. 登陆后可显示主机分组, =根据分组查看主机列表;
3. 可批量执行命令, 发送文件并实时显示结果;
4. 没有基于无密码认证, 每台主机的用户名和主机名均不同;

主机操作设置
settings.py,其所在目录设置为根目录

host_info = {
    'web': {
        'web1': {'ip': '172.25.254.10', 'port': 22, 'username': 'root', 'password': 'redhat'},
        'web2': {'ip': '172.25.254.1', 'port': 22, 'username': 'root', 'password': 'westos'},
        'web3': {'ip': '172.25.254.2', 'port': 22, 'username': 'root', 'password': 'redhat'},
    },
    'mysql': {
        'mysql1': {'ip': '172.25.254.10', 'port': 22, 'username': 'root', 'password': 'redhat'},
        'mysql2': {'ip': '172.25.254.1', 'port': 22, 'username': 'root', 'password': 'westos'}

    },
    'zabbix': {
        'zabbix1': {'ip': '172.25.254.1', 'port': 22, 'username': 'root', 'password': 'westos'}
    }

}

导入settings模块(独立的settings.py文件可以作为模块导入)

import paramiko

from settings import host_info

class RomoteHost(object):
    def __init__(self, host, port, username, password, cmd):
        self.host = host
        self.port = port
        self.username = username
        self.password =  password
        self.cmd = cmd

    def run(self):
        """执行命令时的分离操作"""
        # cmd hostname
        cmd_str = self.cmd.split()[0]  # 第0个索引代表命令
        # 类的反射(hasattr):根据对象,获取对应的类拥有的属性和方法
        if hasattr(self, 'do_'+cmd_str):  # 判断方法'do_'+cmd_str是否存在
            getattr(self, 'do_'+cmd_str)() # 获取方法,后面加括号可以将这个方法运行。
        else:
            print("目前不支持")


    def do_cmd(self):
        # 1. 创建SSH对象;
        ssh = paramiko.SSHClient()

        # 2. 如果之前不再know_host里面, 自动解决yes/no的问题;
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        # 3. 连接服务器
        ssh.connect(hostname=self.host, port=self.port,
                    username=self.username, password=self.password)

        # 4. 远程执行命令
        # self.cmd = 'cmd hostname'

        now_cmd = self.cmd.split()[1:]
        now_cmd = " ".join(now_cmd)   # 命令以空格隔开
        print(now_cmd)
        stdin, stdout, stderr = ssh.exec_command(now_cmd)

        # 5. 获取命令结果;
        result = stdout.read()   # 输出结果
        print("%s".center(50, '*') %(self.host))
        print(result.decode('utf-8'))

        # 6. 关闭ssh连接
        ssh.close()

    def do_put(self):
        transport = paramiko.Transport((self.host, self.port))
        transport.connect(username=self.username, password=self.password)

        sftp = paramiko.SFTPClient.from_transport(transport)

        # put /etc/passwd
        now_cmd = self.cmd.split()[1:]
        if len(now_cmd) == 2:
            file1 = now_cmd[0]  # 本机文件
            file2 = now_cmd[1]  # 上传到服务端的文件(file1 !=file2,即上传中file1改名为file)
            print(file1, file2)
            # 将本机的文件上传到远程服务器上;
            sftp.put(file1, file2)
        elif len(now_cmd) == 1:
            file1 = now_cmd[0]
            sftp.put(file1)
        else:
            print('options error')

        print( print("%s".center(50, '*') %(self.host)))

        # # 下载远程主机的文件到local;
        # sftp.get('/tmp/westos89', '/tmp/qq')

        sftp.close()

    def do_get(self):
        print('get.....')


def select_host_list():
    """列出指定主机组的主机成员信息"""
    # 1. 列出所有的主机组名称
    for index,key in enumerate(host_info):
        print(index+1, key, len(host_info[key]))
    # len(host_info[key] 主机数量
    # 2. 用户选择操作的主机
    while True:
        group = input("选择主机组(eg:web)>>")
        if group not in host_info:
            print('该主机组%s不存在' %(group))
        else:
            # 显示该主机组所有成员的ip:
            groups = host_info[group]
            print("主机组显示".center(50, '*'))
            for key, value in groups.items():
                # item == 'web1',
                print(key, value['ip'])
            # groups是选中的主机组成员所有信息;
            return  groups

def main(choose_host):
    while True:
        # 接收用户对选中主机的操作
        # cmd hostname
        # put /etc/passwd
        # get /etc/passwd
        cmd = input(">>:").strip()
        if cmd:
            # 依次遍历选中的所有主机
            for key in choose_host:
                host = choose_host[key]['ip']
                port = choose_host[key]['port']
                username = choose_host[key]['username']
                password = choose_host[key]['password']

                obj = RomoteHost(host, port, username, password, cmd)
                obj.run()
        else:
            continue

choose_host = select_host_list()
main(choose_host)
/usr/local/python3/bin/python3.6 /root/PycharmProjects/day13/04_基于paramiko的主机批量管理工具.py
1 web 3
2 mysql 2
3 zabbix 1
选择主机组(eg:web)>>web
**********************主机组显示***********************
web1 172.25.254.10
web2 172.25.254.1
web3 172.25.254.2
>>:cmd hostname
hostname
************************172.25.254.10************************
foundation10.example.com

hostname
************************172.25.254.1************************
localhost

hostname
************************172.25.254.2************************
localhost

>>:cmd las
las
************************172.25.254.10************************
bash: las: command not found

las
************************172.25.254.1************************

las
************************172.25.254.2************************
>>: cmd touch /mnt/hello
touch /mnt/hello
************************172.25.254.10************************

touch /mnt/hello
************************172.25.254.1************************

touch /mnt/hello
************************172.25.254.2************************

[root@localhost ~]# ll /mnt/hello 
-rw-r--r--. 1 root root 0 6月  15 08:02 /mnt/hello
[root@localhost ~]# ll /mnt/hello 
-rw-r--r--. 1 root root 0 6月  15 08:02 /mnt/hello
[kiosk@foundation10 mnt]$ ll hello
-rw-r--r-- 1 root root 0 6月  15 20:01 hello

你可能感兴趣的:(python-常用模块)