Python3 学习笔记


关于面向对象

命名空间

命名空间(Namespace)是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的。

命名空间提供了在项目中避免名字冲突的一种方法。各个命名空间是独立的,没有任何关系的,所以一个命名空间中不能有重名,但不同的命名空间是可以重名而没有任何影响。

我们举一个计算机系统中的例子,一个文件夹(目录)中可以包含多个文件夹,每个文件夹中不能有相同的文件名,但不同文件夹中的文件可以重名。

一般有三种命名空间:

  • 内置名称(built-in names), Python 语言内置的名称,比如函数名 abs、char 和异常名称 BaseException、Exception 等等。
  • 全局名称(global names),模块中定义的名称,记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。
  • 局部名称(local names),函数中定义的名称,记录了函数的变量,包括函数的参数和局部定义的变量。(类中定义的也是)

命名空间查找顺序:

假设我们要使用变量 runoob,则 Python 的查找顺序为:局部的命名空间去 -> 全局命名空间 -> 内置命名空间

如果找不到变量 runoob,它将放弃查找并引发一个 NameError 异常:

NameError: name 'runoob' is not defined

作用域

作用域就是一个 Python 程序可以直接访问命名空间的正文区域。

在一个 python 程序中,直接访问一个变量,会从内到外依次访问所有的作用域直到找到,否则会报未定义的错误。

Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。

变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。Python 的作用域一共有4种,分别是:

有四种作用域:

  • L(Local):最内层,包含局部变量,比如一个函数/方法内部。
  • E(Enclosing):包含了非局部(non-local)也非全局(non-global)的变量。比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。
  • G(Global):当前脚本的最外层,比如当前模块的全局变量。
  • B(Built-in): 包含了内建的变量/关键字等,最后被搜索。

规则顺序: L –> E –> G –> B

在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内置中找。

def scope_test():
    def do_local():
        # spam只作用与do_local函数
        spam = "local spam"

    def do_nonlocal():
      # nonlocal语句会使得所列出的名称指向之前在最近的包含作用域中绑定的除全局变量以外的变量,作用与scope_test函数内
        nonlocal spam
        spam = "nonlocal spam"

    def do_global():
      # global语句是作用于整个当前代码块的声明
        global spam
        spam = "global spam"

    spam = "test spam"
    do_local()
    print("After local assignment:", spam)
    do_nonlocal()
    print("After nonlocal assignment:", spam)
    do_global()
    print("After global assignment:", spam)

scope_test()
print("In global scope:", spam)

简介

  • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
  • 方法:类中定义的函数。
  • 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
  • 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
  • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
  • 局部变量:定义在方法中的变量,只作用于当前实例的类。
  • 实例变量:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。
  • 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
  • 实例化:创建一个类的实例,类的具体对象。
  • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

和其它编程语言相比,Python 在尽可能不增加新的语法和语义的情况下加入了类机制。

Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法。

对象可以包含任意数量和类型的数据。

定义类

  • 类有一个名为__init__()的特殊方法(构造方法),该方法在类实例化时会自动调用
  • self代表类的实例,而非类。类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self
  • 在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self, 且为第一个参数,self 代表的是类的实例。
  • 私有属性以两个下划线开头,如:__birthday
#!/usr/bin/python3
import time
class People:
  '''
  定义一个People类
  '''
  # 通过构造函数定义类的属性
  def __init__(self,name,sex,age,birthday=time.strftime("%Y%m%d",time.localtime())):
    self.name=name
    self.sex=sex
    self.age=age
    # 定义类的私有属性,私有属性名称开头为两个下划线,私有属性在类外部无法直接访问,必须使用类的方法访问
    self.__birthday=birthday

  # 定义类的方法
  def getBirthday(self):
    return self.__birthday

# 实例化类
p1=People("Yasso","male","1")
p2=People("Ashe","female","18",20031010)
# 访问类的属性
print("姓名:",p1.name,"性别:",p1.sex,"年龄:",p1.age,"出生日期:",p1.getBirthday())
print("姓名:",p2.name,"性别:",p2.sex,"年龄:",p2.age,"出生日期:",p2.getBirthday())

继承

子类(派生类 DerivedClassName)会继承父类(基类 BaseClassName)的属性和方法。

BaseClassName(实例中的基类名)必须与派生类定义在一个作用域内。除了类,还可以用表达式,基类定义在另一个模块中时这一点非常有用

#!/usr/bin/python3
import time
class People:
  '''
  定义一个人类
  '''
  # 通过构造函数定义类的属性
  def __init__(self,name,sex,age,birthday=time.strftime("%Y%m%d",time.localtime())):
    self.name=name
    self.sex=sex
    self.age=age
    # 定义类的私有属性,私有属性名称开头为两个下划线,私有属性在类外部无法直接访问,必须使用类的方法访问
    self.__birthday=birthday

  # 定义类的方法
  def getBirthday(self):
    return self.__birthday

class MalePeople(People):
  '''
  定义一个男人类,继承人类
  '''
  def __init__(self,name,age,birthday=time.strftime("%Y%m%d",time.localtime())):
    # 调用父类的构造函数
    People.__init__(self,name,"male",age,birthday)

# 实例化类
mp=MalePeople("Jack",20)
# 访问类的属性
print("姓名:",mp.name,"性别:",mp.sex,"年龄:",mp.age,"出生日期:",mp.getBirthday())

多继承

需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索 即方法在子类中未找到时,从左到右查找父类中是否包含方法。

#!/usr/bin/python3
 
#类定义
class people:
    #定义基本属性
    name = ''
    age = 0
    #定义私有属性,私有属性在类外部无法直接进行访问
    __weight = 0
    #定义构造方法
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s 说: 我 %d 岁。" %(self.name,self.age))
 
#单继承示例
class student(people):
    grade = ''
    def __init__(self,n,a,w,g):
        #调用父类的构函
        people.__init__(self,n,a,w)
        self.grade = g
    #覆写父类的方法
    def speak(self):
        print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
 
#另一个类,多重继承之前的准备
class speaker():
    topic = ''
    name = ''
    def __init__(self,n,t):
        self.name = n
        self.topic = t
    def speak(self):
        print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))
 
#多重继承
class sample(speaker,student):
    a =''
    def __init__(self,n,a,w,g,t):
        student.__init__(self,n,a,w,g)
        speaker.__init__(self,n,t)
 
test = sample("Tim",25,80,4,"Python")
test.speak()   #方法名同,默认调用的是在括号中排前地父类的方法

方法和函数的区别是什么

函数(Function)

独立性:函数是一段独立的代码块,可以在程序中多次调用执行。函数可以接受参数,并且可能返回一个值。
独立命名:函数有自己的名称,调用时需要使用该名称。函数通常具有描述性的名字,以说明其功能。
可重用性:函数的设计目的之一是促进代码的重用。可以在不同的地方调用同一个函数来执行相同或类似的任务。
可扩展性:函数的定义和实现是相对独立的,因此可以方便地添加新的函数或修改现有函数,以满足不同的需求。

方法(Method)

与对象关联:方法是与对象(或类)关联的函数。它们定义在类中,并且可以被该类的实例(对象)调用。
隐含参数:方法的第一个参数通常是隐含的,即表示调用该方法的对象本身。在方法内部,可以使用这个参数来访问对象的属性或调用对象的其他方法。
通过对象调用:要调用方法,需要通过对象来调用,语法为对象名.方法名()。调用方法时,对象会自动成为方法的第一个参数。
提供对象的行为:方法定义了对象的行为和操作。它们可以修改对象的状态,访问对象的属性,或者执行与对象相关的其他操作。

二者区别:

所属不同:函数是独立存在的代码块,而方法是与对象关联的函数,在类中定义。
调用方式不同:函数可以直接调用,而方法必须通过对象来调用。
隐含参数:方法的第一个参数通常是隐含的,表示调用方法的对象本身。

argparse模块

ArgumentParser对象

class argparse.ArgumentParser(
    prog=None,                  # 设定程序名称 (defaul: sys.argv[0])
    usage=None,                 # 替换默认的Usage信息
    description=None,           # 程序简要信息说明(参数说明前)
    epilog=None,                # 附加信息说明(参数说明后)
    parents=[],                 # 继承父解析器(parser)
    formatter_class=argparse.HelpFormatter,     # 自定义帮忙信息显示格式(4种)
    prefix_chars='-',           # 参数前缀符号(默认为-,如:-h/--help)
    fromfile_prefix_chars=None, # 从文件中引用参数(与在命令行直接写作用一致,解决参数过多的情况)
    argument_default=None,      # 可设置argparse.SUPPRESS阻止默认参数默认值
    conflict_handler='error',   # 参数冲突处理
    add_help=True,              # 帮助信息中默认添加"-h, --help"描述
    allow_abbrev=True           # 允许参数缩写
)

add_argument()方法

ArgumentParser.add_argument(
    name or flags...    # 选项的名称或列表,例如:foo/-f/--foo
    [, action]      # 采取的基本操作
                        store(默认)         存储参数值
                        store_const        使用该字符串选项时,取用const值
                        store_true         使用该字符串选项时,参数值置为True
                        store_false        使用该字符串选项时,参数值置为False
                        append             同一个命令行中多次使用该字符串选项时,以追加的方式将值添加到list中
                        append_const       将多个字符串选项的const值合并到一个list
                        count              统计选项出现的次数 (如:"-vvv",则最终值为3)
                        help               parser默认会添加一个help action。(一般不用理会)
                        version            打印版本信息
                        也可以自定义action类
    [, nargs]       # 该参数值要求的数量
                        数值       指明参数个数
                        ?         提供了参数则取参数值;
                                    无参数但声明了选项字符串则取const值;
                                    无参数也未声明选择字符串则取default值
                        *         所有参数存入list
                        +         与*类似,但参数个数不能为空
                        argparse.REMAINDER  原封不动的记录参数到list中,通常用于将这些参数传递到其它的命令行工具。
    [, const]       # action/nargs部分要求的常值
                        1、当action="store_const"或者"append_const"时需要设置
                        2、当选项为(-f/--foo),nargs='?',同时未提供具体参数时,取用该值。
    [, default]     # 参数默认值
    [, type]        # 参数类型(内建参数或者函数,也可是自定义函数)
    [, choices]     # 允许的参数值(白名单),tuple/range
    [, required]    # 选项是否必须,设置为True表示选项必填。
    [, help]        # 参数说明,可以用其它类似 %(prog)s 格式调用prog值;可设置argparse.SUPPRESS使该选项在帮助信息中不可见。
    [, metavar]     # 定义参数在Usage信息中的名称
    [, dest]        # 解析后的属性名称
)
  • 自定义action
    class argparse.Action(option_strings, dest, nargs=None, const=None, default=None, type=None, choices=None, required=False, help=None, metavar=None)

parse_args()方法

ArgumentParser.parse_args(args=None, namespace=None)

一般情况下,我们直接使用如下命令就可以了:

# args=None, 程序将sys.argv作为参数代入args = parse.parse_args()
# 给args赋值,跳过sys.argv,主要用于测试工作,避免每次运行都输入冗长的参数。args = parser.parse_args(['1', '2', '3', '4'])
# namespace=custom_class,将属性分配到一个已经存在的对象中。parser.parse_args(args=['--foo', 'BAR'], namespace=custom_class99)

其它工具

  • 子命令
    很多程序把它的功能分到几个子程序中,比如:pip install , pip download , pip uninstall 等. 通过这种方式,可以很方便处理不同程序的参数。
    ArgumentParser.add_subparsers(title, prog, action, dest[, metavar])
>>> parser = argparse.ArgumentParser()
>>> subparsers = parser.add_subparsers(dest='subparser_name')
>>> subparser1 = subparsers.add_parser('1')
>>> subparser1.add_argument('-x')
>>> subparser2 = subparsers.add_parser('2')
>>> subparser2.add_argument('y')
>>> parser.parse_args(['2', 'frobble'])Namespace(subparser_name='2', y='frobble')
  • 文件类型对象
    add_argument()中的FileType的参数”工厂”。
    class argparse.FileType(mode=’r’, bufsize=-1, encoding=None, errors=None)
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--raw', type=argparse.FileType('wb', 0))
>>> parser.add_argument('out', type=argparse.FileType('w', encoding='UTF-8'))
>>> parser.parse_args(['--raw', 'raw.dat', 'file.txt'])Namespace(out=<_io.TextIOWrapper name='file.txt' mode='w' encoding='UTF-8'>, raw=<_io.FileIO name='raw.dat' mode='wb'>)
  • 参数分组
    在Usage信息中的参数分组,如pip -h可以看到”Commands”,”General Options”分组。
    ArgumentParser.add_argument_group(title=None, description=None)
>>> parser = argparse.ArgumentParser(prog='testPROG', add_help=False)
>>> group1 = parser.add_argument_group('group1', 'group1 description')
>>> group1.add_argument('foo', help='foo help')
>>> group2 = parser.add_argument_group('group2', 'group2 description')
>>> group2.add_argument('--bar', help='bar help')
>>> parser.print_help()
usage: testPROG [--bar BAR] foogroup1:group1 descriptionfoo    foo helpgroup2:group2 description--bar BAR  bar help
  • 互斥
    参数互斥!
    ArgumentParser.add_mutually_exclusive_group(required=False)
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> group = parser.add_mutually_exclusive_group(required=True)
>>> group.add_argument('--foo', action='store_true')
>>> group.add_argument('--bar', action='store_false')
>>> parser.parse_args([])usage: PROG [-h] (--foo | --bar)PROG: error: one of the arguments --foo --bar is required

示例代码

import argparse
#建立解析器
parser=argparse.ArgumentParser(description="程序描述语",epilog="结语")
#添加必需参数,并且按照输入顺序进行设定
#parser.add_argument('host',help='定义必选参数host')
#添加可选参数p,int类型,默认值为80
parser.add_argument('-p',type=int,default=80,help='定义可选参数p') 
#定义可选参数BOOL参数state,并设置默认值为True
parser.add_argument('-s','--state',action='store_true',help='有该参数则值为True,否则为False')
#设置可选参数的取值范围
parser.add_argument('-c',help='设置参数的可选值,若未设置则默认值为 None',choices=['one', 'two', 'three', 'four'])
parser.add_argument('--default','-d',help='default 可以设置默认值',choices=['one', 'two', 'three', 'four'],default = 'one')
#设置参数为文件类型,可通过encoding参数设置编码格式
parser.add_argument('-f',type=argparse.FileType('r',encoding='utf8'),help='读取文件')
#以wb格式打开文件
parser.add_argument('--raw', type=argparse.FileType('wb', 0),help='以二进制模式打开文件')
#以文本模式打开文件
parser.add_argument('-o', type=argparse.FileType('w', encoding='UTF-8'),help='以文本模式打开文件')
#获取参数的值,返回为命名空间类型
args = parser.parse_args()
print("默认返回Namespace类型参数:",args)
print(args.p)
print(args.state)
#以二进制模式打开的文件写入参数为bytes类型
#args.raw.write(b'aaaaaaaaaaaaaaaaaaaa')
#以文本模式打开的文件写入参数为str类型
#args.o.write('bbbbbbbbbbbbbbbbbbbbbb')
params = vars(args)
print("字典类型:",params)

asyncio模块

异步模块asyncio是用来做异步网络、并发、协程等操作。python3.0时代,标准库里的异步网络模块:select(非常底层) ,第三方异步网络库:Tornado。python3.4时代,asyncio:支持TCP,子进程

现在的asyncio,有了很多的模块已经在支持:aiohttp,aiodns,aioredis等等。

关于asyncio的一些关键字的说明:

  • event_loop 事件循环:程序开启一个无限循环,把一些函数注册到事件循环上,当满足事件发生的时候,调用相应的协程函数
  • coroutine 协程:协程对象,指一个使用async关键字定义的函数,它的调用不会立即执行函数,而是会返回一个协程对象。协程对象需要注册到事件循环,由事件循环调用。
  • task 任务:一个协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含了任务的各种状态
  • future: 代表将来执行或没有执行的任务的结果。它和task上没有本质上的区别
  • async/await 关键字:python3.5用于定义协程的关键字,async定义一个协程,await用于挂起阻塞的异步调用接口。

https://blog.csdn.net/whatday/article/details/100560546

协程的定义

直接在函数前加async,如:

async def func(x,y):
    print(x+y)

可以通过 asyncio.iscoroutinefunction 来验证协程,如:

if asyncio.iscoroutinefunction(func))==True:
    print("This is a async")

要让这个协程对象运行的话,有两种方式:

  • 在另一个已经运行的协程中用 await 等待它
  • 通过 ensure_future 函数计划它的执行

简单来说,只有 loop 运行了,协程才可能运行。下面先拿到当前线程缺省的 loop ,然后把协程对象交给 loop.run_until_complete,协程对象随后会在 loop 里得到运行

loop = asyncio.get_event_loop()
loop.run_until_complete(func(3,4))

run_until_complete 是一个阻塞(blocking)调用,直到协程运行结束,它才返回。这一点从函数名不难看出。run_until_complete 的参数是一个 future,但是我们这里传给它的却是协程对象,之所以能这样,是因为它在内部做了检查,通过 ensure_future 函数把协程对象包装(wrap)成了 future。所以,我们可以写得更明显一些:

loop.run_until_complete(asyncio.ensure_future(func(3,4)))

https://blog.csdn.net/cqcre/article/details/104687750/

BeautifulSoup模块

安装

pip install beautifulsoup4 lxml

解析器比较

解析器使用方法优势劣势
Python标准库BeautifulSoup(markup, "html.parser")Python的内置标准库、执行速度适中、文档容错能力强Python 2.7.3及Python 3.2.2之前的版本文档容错能力差
lxml HTML解析器BeautifulSoup(markup, "lxml")速度快、文档容错能力强需要安装C语言库
lxml XML解析器BeautifulSoup(markup, "xml")速度快、唯一支持XML的解析器需要安装C语言库
html5libBeautifulSoup(markup, "html5lib")最好的容错性、以浏览器的方式解析文档、生成HTML5格式的文档速度慢、不依赖外部扩展

使用

# 导入模块
from bs4 import BeautifulSoup
import requests, re

req_obj = requests.get('https://www.baidu.com')
soup = BeautifulSoup(req_obj.text, 'lxml')

'''标签查找'''
print(soup.title)  # 只是查找出第一个
print(soup.find('title'))  # 效果和上面一样
print(soup.find_all('div'))  # 查出所有的div标签

'''获取标签里的属性'''
tag = soup.div
print(tag['class'])  # 多属性的话,会返回一个列表
print(tag['id'])  # 查找标签的id属性
print(tag.attrs)  # 查找标签所有的属性,返回一个字典(属性名:属性值)

'''标签包的字符串'''
tag = soup.title
print(tag.string)  # 获取标签里的字符串
tag.string.replace_with("哈哈")  # 字符串不能直接编辑,可以替换

'''子节点的操作'''
tag = soup.head
print(tag.title)  # 获取head标签后再获取它包含的子标签

'''contents 和 .children'''
tag = soup.body
print(tag.contents)  # 将标签的子节点以列表返回
print([child for child in tag.children])  # 输出和上面一样

'''descendants'''
tag = soup.body
[print(child_tag) for child_tag in tag.descendants]  # 获取所有子节点和子子节点

'''strings和.stripped_strings'''
tag = soup.body
[print(str) for str in tag.strings]  # 输出所有所有文本内容
[print(str) for str in tag.stripped_strings]  # 输出所有所有文本内容,去除空格或空行

'''.parent和.parents'''
tag = soup.title
print(tag.parent)  # 输出便签的父标签
[print(parent) for parent in tag.parents]  # 输出所有的父标签

'''.next_siblings 和 .previous_siblings
    查出所有的兄弟节点
'''

'''.next_element 和 .previous_element
    下一个兄弟节点
'''

'''find_all的keyword 参数'''
soup.find_all(id='link2')  # 查找所有包含 id 属性的标签
soup.find_all(href=re.compile("elsie"))  # href 参数,Beautiful Soup会搜索每个标签的href属性:
soup.find_all(id=True)  # 找出所有的有id属性的标签
soup.find_all(href=re.compile("elsie"), id='link1')  # 也可以组合查找
soup.find_all(attrs={"属性名": "属性值"})  # 也可以通过字典的方式查找

soup.find_all("a")等价soup("a")

bytearray模块

bytearray() 方法返回一个新字节数组。这个数组里的元素是可变的,并且每个元素的值范围: 0 <= x < 256

buf=b"\x00\x01\x02\x03"
bytearray(buf)

ctypes模块

加载动态链接库

import ctypes
#加载Windows动态链接库
#windll方法调用kernel32.dll
ctypes.windll.kernel32
#cdll方法调用msvcrt.dll
ctypes.cdll.msvcrt
#加载Linux动态链接库
#LoadLibrary方法加载
ctypes.cdll.LoadLibrary("libc.so.6")
#通过构造函数CDLL创建实例
libc=ctypes.CDLL("libc.so.6")

访问动态链接库的函数

import ctypes
#通过属性访问
wlib=ctypes.windll.kernel32
#GetModuleHandleA表示ANSI版本,GetModuleHandleW表示UNICODE版本
wlib.GetModuleHandleA
#ctypes.windll.kernel32.GetModuleHandleA
#通过序号访问
wlib[1]
#ctypes.windll.kernel32[1]
#ctypes.cdll.kernel32[1]

调用函数

import ctypes
wlib=ctypes.windll.kernel32
#调用函数
wlib.GetModuleHandleW()
wlib.GetVersionExW()
wlib.GetEnvironmentVariableW(None)

数据类型

ctypes类型C型Python类型
c_bool_Bool布尔(1)
c_charchar1个字符的字节对象
c_wcharwchar_t1个字符的字符串
c_bytechar整型
c_ubyteunsigned char整型
c_shortshort整型
c_ushortunsigned short整型
c_intint整型
c_uintunsigned int整型
c_longlong整型
c_ulongunsigned long整型
c_longlong__int64 要么 long long整型
c_ulonglongunsigned __int64 要么 unsigned long long整型
c_size_tsize_t整型
c_ssize_tssize_t 要么 Py_ssize_t整型
c_floatfloat浮动
c_doubledouble浮动
c_longdoublelong double浮动
c_char_pchar * (NUL终止)字节对象或 None
c_wchar_pwchar_t * (NUL终止)字符串或 None
c_void_pvoid *int或 None

除整数,字符串和字节对象外,所有Python类型都必须包装在它们对应的ctypes类型中

execjs模块

安装

pip install PyExecJS

使用

a.js文件内容

var createGuid = function() {
        return (((1 + Math.random()) * 65536) | 0).toString(16).substring(1)
    };
 
var guid = createGuid() + createGuid() + "-" + createGuid() + "-" + createGuid() + createGuid() + "-" + createGuid() + createGuid() + createGuid();

Python调用

#!/usr/bin/python3
import execjs

jsfile=open('a.js','r',encoding='utf8').read()
# 编译执行JS脚本
getpass=execjs.compile(jsfile)
# 调用JS脚本中的函数createGuid
mypass=getpass.call('createGuid')
print(mypass)
# 调用变量
res = docjs.eval('guid')
print(res)

futures模块

gevent模块

hashlib模块

md5

具体代码如下:

import hashlib
ha_m5 = hashlib.md5()#创建对象
ha_m5.update('abc'.encode(encoding='utf-8'))#添加对象时需要指定编码
print(ha_m5.digest())#以二进制格式显示加密信息
print(ha_m5.hexdigest())#以十六进制格式显示加密信息(常用)

sha1

具体代码如下:

ha_s1 = hashlib.sha1()
ha_s1.update('abc'.encode(encoding='utf-8'))
print(ha_s1.digest())
print(ha_s1.hexdigest())

sha224

具体代码如下:

ha_s224 = hashlib.sha224()
ha_s224.update('abc'.encode(encoding='utf-8'))
print(ha_s224.digest())
print(ha_s224.hexdigest())

sha256

具体代码如下:

ha_s256 = hashlib.sha256()
ha_s256.update('abc'.encode(encoding='utf-8'))
print(ha_s256.digest())
print(ha_s256.hexdigest())

sha384

具体代码如下:

ha_s384 = hashlib.sha384()
ha_s384.update('abc'.encode(encoding='utf-8'))
print(ha_s384.digest())
print(ha_s384.hexdigest())

sha512

具体代码如下:

ha_s512 = hashlib.sha224()
ha_s512.update('abc'.encode(encoding='utf-8'))
print(ha_s512.digest())
print(ha_s512.hexdigest())

注:加密是对数据的整体加密,即进行加密时当前的数据进行整体加密。

hmac模块

该模块加密是先把数据存储到字典中,然后再进行加密,方法与上述方法类似。

具体代码如下:

import hmac
hm = hmac.new(b'abc')
hm = hmac.new('萨芬'.encode(encoding='utf-8'),b'bads')
print(hm.digest())
print(hm.hexdigest())

注:加密数据时一定要指定数据编码格式。

itertools模块

json模块

load方法

# 读取json数据
json.loads(json.loads('{"a":"b"}'.encode('utf8')))
# 从文件读取
json.load(open('data.json','r',encoding='utf8'))

dump方法

# 生成json数据
json.dumps({'a':'b'})
# 生成json文件
f=open('data.json','w')
json.dump({'a':'b'},f)

loguru模块

安装

pip3 install loguru

简单使用

from loguru import logger

logger.debug('this is a debug message')
logger.info('this is another debug message')
logger.warning('this is another debug message')
logger.error('this is another debug message')
logger.info('this is another debug message')
logger.success('this is success message!')
logger.critical('this is critical message!')

颜色

https://loguru.readthedocs.io/en/stable/api/logger.html#color

from loguru import logger
from sys import stdout

logger.remove()
logger.add(stdout,colorize=True,format="<g>[{time:HH:mm:ss}]  [DEBUG]  {message}</g>")
logger.debug("正在安装工具")
logger.info("aaaaa")

multiprocessing模块

numpy模块

openpyxl模块

创建文件

from  openpyxl import  Workbook 
# 实例化
wb = Workbook()
# 激活 worksheet
ws = wb.active

打开存在的文件

from openpyxl  import load_workbook
wb2 = load_workbook('文件名称.xlsx')

写入数据

# 方式一:数据可以直接分配到单元格中(可以输入公式)
ws['A1'] = 42
# 方式二:可以附加行,从第一列开始附加(从最下方空白处,最左开始)(可以输入多行)
ws.append([1, 2, 3])
# 方式三:Python 类型会被自动转换
ws['A3'] = datetime.datetime.now().strftime("%Y-%m-%d")

创建表(Sheet)

# 方式一:插入到最后(default)
ws1 = wb.create_sheet("Mysheet")
# 方式二:插入到最开始的位置
ws2 = wb.create_sheet("Mysheet", 0)

改变Sheet颜色

ws.sheet_properties.tabColor = "1072BA"

选择表

# sheet 名称可以作为 key 进行索引
ws3 = wb["New Title"]
ws4 = wb.get_sheet_by_name("New Title")

删除表

wb.remove(wb['Sheet'])

保存数据

wb.save('test.xlsx')

optparse模块

示例代码:

import optparse
parser=optparse.OptionParser('%prog -u [url] -c [cmd]')
parser.add_option('-u','--url',dest='target_url',help='目标url')
parser.add_option('-c',dest='cmd',help='需要执行的命令')
(options,args)=parser.parse_args()
print(options.target_url)
print(options.cmd)

os模块

os.getcwd() -- 类似pwd
os.chdir("../") -- 类似cd
os.curdir() -- 返回当前目录
os.pardir() -- 获取当前目录的父目录
os.remove("/file") -- 永久删除文件
os.rename(old,new) -- 重命名
os.mkdir() -- 创建文件夹
os.makedirs() -- 递归创建目录
os.rmdir() -- 删除空目录
os.removedirs() -- 递归删除空目录
os.listdir(path) -- 获取当前目录下文件列表
os.stat() -- 获取文件或目录信息
os.sep() -- 输出操作系统路径分隔符
os.pathsep() -- 环境变量分隔符
os.name() -- 输出当前使用平台
os.path.abspath("../") -- 返回绝对路径
os.path.split() -- 分割目录
os.path.dirname("/home/a.txt") -- 取路径,如:/home
os.path.basename("/home/a.txt") -- 取文件,如:a.txt
os.path.exists() -- 判断路径是否存在
os.path.isabs() -- 判断路径是否为绝对路径
os.path.isfile() -- 判断是否为文件
os.path.isdir() -- 判断是否为目录
os.path.join() -- 组合路径
os.path.getatime() -- 获取最后存取时间
os.path.getmtime() -- 获取修改时间
os.popen() -- 执行命令不直接返回

paramiko模块

简介

paramiko是一个遵循SSH2协议,支持加密和认证方式,连接远程服务器执行命令或者上传下载文件,用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作,基于linux中的ssh服务。paramiko属于第三方模块,需要安装导入。

SSH执行命令

#!/usr/bin/python3
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect("某IP地址",22,"用户名", "口令")
stdin, stdout, stderr = ssh.exec_command("你的命令")
print stdout.readlines()
ssh.close()

SFTP文件上传

#!/usr/bin/python3
import paramiko
t = paramiko.Transport(("某IP地址",22))
t.connect(username = "用户名", password = "口令")
sftp = paramiko.SFTPClient.from_transport(t)
remotepath='/tmp/test.txt'
localpath='/tmp/test.txt'
sftp.put(localpath,remotepath)
t.close()

SFTP文件下载

#!/usr/bin/python
import paramiko
t = paramiko.Transport(("某IP地址",22))
t.connect(username = "用户名", password = "口令")
sftp = paramiko.SFTPClient.from_transport(t)
remotepath='/tmp/test.txt'
localpath='/tmp/test.txt'
sftp.get(remotepath, localpath)
t.close()

pexpect模块

该模块用于自动化与程序交互。

spawn() 方法

启动一个子进程执行命令

expect()方法

利用正则表达式来匹配所需的关键字,返回 0 表示匹配到了所需的关键字,如果后面的匹配关键字是一个列表的话,就会返回一个数字表示匹配到了列表中第几个关键字,从 0 开始计算。

import pexpect
process = pexpect.spawn('ftp 127.0.0.1')
index=process.expect([""])

pickle模块

pickle模块实现了用于序列化和反序列化Python对象结构的二进制协议。 “Pickling”是将Python对象层次结构转换为字节流的过程, “unpickling”是反向操作,从而将字节流(来自二进制文件或类似字节的对象)转换回对象层次结构。pickle模块对于错误或恶意构造的数据是不安全的。
注意:使用该模块需要特别注意避免造成反序列化漏洞。

pickle协议和JSON(JavaScript Object Notation)的区别 :

  1. JSON是一种文本序列化格式(它输出unicode文本,虽然大部分时间它被编码utf-8),而pickle是二进制序列化格式;
  2. JSON是人类可读的,而pickle则不是;
  3. JSON是可互操作的,并且在Python生态系统之外广泛使用,而pickle是特定于Python的;

默认情况下,JSON只能表示Python内置类型的子集,而不能表示自定义类; pickle可以表示极其庞大的Python类型(其中许多是自动的,通过巧妙地使用Python的内省工具;复杂的案例可以通过实现特定的对象API来解决)。

pickle 数据格式是特定于Python的。它的优点是没有外部标准强加的限制,例如JSON或XDR(不能代表指针共享); 但是这意味着非Python程序可能无法重建pickled Python对象。

默认情况下,pickle数据格式使用相对紧凑的二进制表示。如果您需要最佳尺寸特征,则可以有效地压缩数据。

pickle与cpickle比较

  • pickle完全用python来实现的,cpickle用C来实现的,cpickle的速度要比pickle快好多倍,电脑中如果有cpickle的话建议使用cpickle。

pickle模块中常用的函数:

  1. pickle.dump(obj, file, [,protocol])

    • 含义:pickle.dump(对象,文件,[使用协议])
    • 将要持久化的数据“对象”,保存到“文件”中,使用有3种协议,索引0为ASCII,1为旧式二进制,2为新式二进制协议,不同之处在于2要更高效一些。
    • 默认dump方法使用0做协议
#!/usr/bin/python3
import pickle

content = {" name ": "Tom", "age": "40"}
f=open('a.txt','wb')
//序列化
pickle.dump(content,f)
f.close()

f=open('a.txt','rb')
c=f.read()
print(len(c))
f.close()

  1. pickle.load(file)

    • 含义:pickle.load(文件),将file中的对象序列化读出。
    • 从“文件”中读取字符串,将他们反序列化转换为python的数据对象,可以像操作数据类型的这些方法来操作它们;**
#!/usr/bin/python3
import pickle
with open('a.txt','rb') as f:
    content=pickle.load(f)
print(content)

  1. pickle.dumps(obj[, protocol])

    • 函数的功能:将obj对象序列化为string形式,而不是存入文件中。
    • obj:想要序列化的obj对象。
    • protocal:如果该项省略,则默认为0。如果为负值或HIGHEST_PROTOCOL,则使用最高的协议版本。
  2. pickle.loads(string)
    pickle.loads是会解决import 问题,对于未引入的module会自动尝试import。那么也就是说整个python标准库的代码执行、命令执行函数我们都可以使用

    • 函数的功能:从string中读出序列化前的obj对象。
    • string:文件名称。

dump()load() 相比 dumps()loads() 还有另一种能力:dump()函数能一个接一个地将几个对象序列化存储到同一个文件中,随后调用load()来以同样的顺序反序列化读出这些对象。

pycryptodome模块

pycurl模块

progressbar模块

platform模块

import platform
platform.platform() #获取操作系统名称及版本号,'Windows-7-6.1.7601-SP1'
platform.version() #获取操作系统版本号,'6.1.7601'
platform.architecture() #获取操作系统的位数,('32bit', 'WindowsPE')
platform.machine() #计算机类型,'x86'
platform.node() #计算机的网络名称,'hongjie-PC'
platform.processor() #计算机处理器信息,'x86 Family 16 Model 6 Stepping 3, AuthenticAMD'
platform.uname() #包含上面所有的信息汇总,uname_result(system='Windows', node='hongjie-PC',
release='7', version='6.1.7601', machine='x86', processor='x86 Family
16 Model 6 Stepping 3, AuthenticAMD')

获取计算机中python信息

import platform
platform.python_build()
platform.python_compiler()
platform.python_branch()
platform.python_implementation()
platform.python_revision()
platform.python_version()
platform.python_version_tuple()
#global var
#是否显示日志信息
SHOW_LOG = True
 
def get_platform():
'''获取操作系统名称及版本号'''
  return platform.platform()
 
def get_version():
'''获取操作系统版本号'''
  return platform.version()
 
def get_architecture():
'''获取操作系统的位数'''
  return platform.architecture()
 
def get_machine():
'''计算机类型'''
  return platform.machine()
 
def get_node():
'''计算机的网络名称'''
  return platform.node()
 
def get_processor():
'''计算机处理器信息'''
  return platform.processor()
 
def get_system():
'''获取操作系统类型'''
  return platform.system()
 
def get_uname():
'''汇总信息'''
  return platform.uname()
 
def get_python_build():
''' the Python build number and date as strings'''
  return platform.python_build()
 
def get_python_compiler():
'''Returns a string identifying the compiler used for compiling Python'''
  return platform.python_compiler()
 
def get_python_branch():
'''Returns a string identifying the Python implementation SCM branch'''
  return platform.python_branch()
 
def get_python_implementation():
'''Returns a string identifying the Python implementation. Possible return values are: ‘CPython’, ‘IronPython’, ‘Jython’, ‘PyPy’.'''
  return platform.python_implementation()
 
def get_python_version():
'''Returns the Python version as string 'major.minor.patchlevel''''
  return platform.python_version()
 
def get_python_revision():
'''Returns a string identifying the Python implementation SCM revision.'''
  return platform.python_revision()
 
def get_python_version_tuple():
'''Returns the Python version as tuple (major, minor, patchlevel) of strings'''
  return platform.python_version_tuple()
 
def show_python_all_info():
'''打印python的全部信息'''
  print('The Python build number and date as strings : [{}]'.format(get_python_build()))
  print('Returns a string identifying the compiler used for compiling Python : [{}]'.format(get_python_compiler()))
  print('Returns a string identifying the Python implementation SCM branch : [{}]'.format(get_python_branch()))
  print('Returns a string identifying the Python implementation : [{}]'.format(get_python_implementation()))
  print('The version of Python : [{}]'.format(get_python_version()))
  print('Python implementation SCM revision : [{}]'.format(get_python_revision()))
  print('Python version as tuple : [{}]'.format(get_python_version_tuple()))
  
def show_python_info():
'''只打印python的信息,没有解释部分'''
  print(get_python_build())
  print(get_python_compiler())
  print(get_python_branch())
  print(get_python_implementation())
  print(get_python_version())
  print(get_python_revision())
  print(get_python_version_tuple())
 
def show_os_all_info():
'''打印os的全部信息'''
print('获取操作系统名称及版本号 : [{}]'.format(get_platform()))
print('获取操作系统版本号 : [{}]'.format(get_version()))
print('获取操作系统的位数 : [{}]'.format(get_architecture()))
print('计算机类型 : [{}]'.format(get_machine()))
print('计算机的网络名称 : [{}]'.format(get_node()))
print('计算机处理器信息 : [{}]'.format(get_processor()))
print('获取操作系统类型 : [{}]'.format(get_system()))
print('汇总信息 : [{}]'.format(get_uname()))

python-nmap模块

scan( host , port , args ) 方法

以指定方式扫描指定主机或网段的指定端口

参数:

  • host : 要扫描的主机或网段,可以是一个单独的ip:192.168.10.10 ;也可以是一个小范围网段:192.168.10.10-20 ;也可以是一个大网段:192.168.10.0/24
  • port : 可选参数,要扫描的端口,多个端口用逗号隔开,如:20,21,22,23,24
  • args :可选参数,要扫描的方式
import nmap
nmScan=nmap.PortScanner()
nm.scan('192.168.10.10-100', '22,21','-sV')
#也可以这样
#nm.scan(hosts='192.168.1.0/24', arguments='-n -sP -PE -PA21,23,80,3389')

command_line() 方法

返回的扫描方法映射到具体的nmap命令行,也就是我们上面执行的nm.scan()命令,对应的具体的nmap的命令

import nmap
nm = nmap.PortScanner()
nm.scan('192.168.10.10-100', '22,21','-sV') 
a=nm.command_line()
print(a)
###########################
nmap -oX - -p 20,21 -sV 192.168.125.134

scaninfo() 方法

返回nmap扫描信息,格式为字典类型

import nmap
nm = nmap.PortScanner()
nm.scan('192.168.10.10-100', '22,21','-sV')
a=nm.scaninfo()
print(a)
###########################
{'tcp': {'services': '20-21', 'method': 'syn'}}

all_hosts() 方法

返回nmap扫描的主机清单,格式为列表类型

import nmap
nm = nmap.PortScanner()
nm.scan('192.168.10.10-12', '22,21','-sV')
####################################################
['192.168.10.10','192.168.10.11','192.168.10.12']

查看扫描主机的详细信息: nm['192.168.125.134']

import nmap
nm=nmap.PortScanner()
nm.scan('192.168.125.134','445')
a=nm['192.168.125.134']    #返回主机的详细信息
print(a)
##################################
{'status': {'state': 'up', 'reason': 'arp-response'}, 
'hostnames': [{'type': 'PTR', 'name': 'bogon'}], 
'vendor': {'00:0C:29:F6:2B:F0': 'VMware'}, 
'addresses': {'mac': '00:0C:29:F6:2B:F0', 'ipv4': '192.168.125.134'}, 
'tcp': {445: {'product': 'Microsoft Windows 7 - 10 microsoft-ds', 'state': 'open', 'version': '', 'name': 'microsoft-ds', 'conf': '10', 'extrainfo': 'workgroup: WORKGROUP', 'reason': 'syn-ack', 'cpe': 'cpe:/o:microsoft:windows'}}}

查看主机扫描的端口包含的协议(TCP/UDP):nmap['192.168.125.134'].all_protocols() 返回列表型数据

import nmap
nm=nmap.PortScanner()
nm.scan('192.168.125.134','445')
a=nm['192.168.125.134'].all_protocols()    #返回主机扫描的端口包含的协议
print(a)
##################################
['tcp']

查看扫描的端口哪些端口提供了TCP协议:nmap['192.168.125.134']['tcp']

import nmap
nm=nmap.PortScanner()
nm.scan('192.168.125.134','445')
a=nm['192.168.125.134']['tcp']        #返回主机扫描的端口哪些端口包含了TCP协议,返回具体信息
b=nm['192.168.125.134']['tcp'].keys()  #只返还端口,返回列表型数据
print(a)
print(b)
##################################
{445: {'product': 'Microsoft Windows 7 - 10 microsoft-ds', 'state': 'open', 'version': '', 'name': 'microsoft-ds', 'conf': '10', 'extrainfo': 'workgroup: WORKGROUP', 'reason': 'syn-ack', 'cpe': 'cpe:/o:microsoft:windows'}}
[445]

查看该端口是否提供了TCP协议:nmap['192.168.125.134'].has_tcp(445) ,返回布尔类型的数据

import nmap
nm=nmap.PortScanner()
nm.scan('192.168.125.134','445')
a=nm['192.168.125.134'].has_tcp(445)        #判断该端口是否提供TCP协议
print(a)
##################################
True

查看该协议下端口的状态:nmap['192.168.125.134']['tcp'][445][state]

import nmap
nm=nmap.PortScanner()
nm.scan('192.168.125.134','445')
a=nm['192.168.125.134']['tcp'][445]['state']
print(a)
##################################
open

queue模块

re模块

re.findall

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。

re.findall(pattern, string, flags=0)
或
pattern.findall(string[, pos[, endpos]])

参数:

  • pattern 匹配模式。
  • string 待匹配的字符串。
  • pos 可选参数,指定字符串的起始位置,默认为 0。
  • endpos 可选参数,指定字符串的结束位置,默认为字符串的长度。
import re
 
result1 = re.findall(r'\d+','runoob 123 google 456')
 
pattern = re.compile(r'\d+')   # 查找数字
result2 = pattern.findall('runoob 123 google 456')
result3 = pattern.findall('run88oob123google456', 0, 10)
 
print(result1)
print(result2)
print(result3)

re.finditer

和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。

re.finditer(pattern, string, flags=0)

参数:

参数描述
pattern匹配的正则表达式
string要匹配的字符串。
flags标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:https://www.runoob.com/python3/python3-reg-expressions.html#flags
import re
 
it = re.finditer(r"\d+","12a32bc43jf3") 
for match in it: 
    print (match.group() )

re.split

split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:

re.split(pattern, string[, maxsplit=0, flags=0])

参数:

参数描述
pattern匹配的正则表达式
string要匹配的字符串。
maxsplit分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。
flags标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:https://www.runoob.com/python3/python3-reg-expressions.html#flags
>>>import re
>>> re.split('\W+', 'runoob, runoob, runoob.')
['runoob', 'runoob', 'runoob', '']
>>> re.split('(\W+)', ' runoob, runoob, runoob.') 
['', ' ', 'runoob', ', ', 'runoob', ', ', 'runoob', '.', '']
>>> re.split('\W+', ' runoob, runoob, runoob.', 1) 
['', 'runoob, runoob, runoob.']
 
>>> re.split('a*', 'hello world')   # 对于一个找不到匹配的字符串而言,split 不会对其作出分割
['hello world']

requests模块

URL编解码

from urllib.parse import unquote,quote
quote("aaa")

解决requests默认url编码的方法:unquote("%23")

上传文件

import requests
 
url = 'http://127.0.0.1:8080/upload'
files = {'file': open('/home/rxf/test.jpg', 'rb')}
#files = {'file': ('report.jpg', open('/home/lyb/sjzl.mpg', 'rb'))}     #显式的设置文件名
 
r = requests.post(url, files=files)
print(r.text)

设置代理

import requests
proxies = {
           "http": "http://10.10.1.10:3128",
           "https": "http://10.10.1.100:4444",
          }
r = requests.get('http://m.ctrip.com', proxies=proxies)

绕过HTTPS验证

import requests

# 屏蔽warning信息
requests.packages.urllib3.disable_warnings()

url = r'https://gdc-api.nci.nih.gov/data/'
UUID = r'7661a652-f22c-4c01-8851-2b9cf6edd739'
url = os.path.join(url, UUID)

req = requests.get(url,verify=False)

提交Json数据

import requests
url ="http://httpbin.org/post"
# 添加json数据
json = {
    "username":"AnJing",
    "password":"123456"
}
# 通过json方式添加数据
r =requests.post(url,json=json)
print(r.text)

socket模块

shelve模块

方法

shelve.open(filename, flag=’c’, protocol=None, writeback=False)
创建或打开一个shelve对象。shelve默认打开方式支持同时读写操作。

参数

  • filename:关联的文件路径。
  • flag(可选参数):默认为c,表示如果数据文件不存在,就创建,允许读写。还可以是: r: 只读;w: 可读写; n: 每次调用open()都重新创建一个空的文件,可读写。
  • protocol:序列化模式,默认值为None。具体还没有尝试过,从pickle的资料中查到:protocol的值可以是1或2,表示以二进制的形式序列化。
  • writeback:默认为False。当设置为True以后,shelve将会将所有从DB中读取的对象存放到一个内存缓存。当我们close()打开的shelve的时候,缓存中所有的对象会被重新写入DB。writeback方式有优点也有缺点:

    • 优点是减少了我们出错的概率,并且让对象的持久化对用户更加的透明了;但这种方式并不是所有的情况下都需要,首先,使用writeback以后,shelveopen()的时候会增加额外的内存消耗,并且当DB在close()的时候会将缓存中的每一个对象都写入到DB,这也会带来额外的等待时间。因为shelve没有办法知道缓存中哪些对象修改了,哪些对象没有修改,因此所有的对象都会被写入。

shelve.close()
同步并关闭shelve对象。
注意:每次使用完毕,都必须确保shelve对象被安全关闭。

示例代码

序列化

s=shelve.open("data.dat")
s["a"]={"name":"Bob","age":22,"info":"Hello"}
s["b"]=[1,2,3,4]
s.close()

反序列化

s.shelve.open("data.dat")
print(s["a"])
print(s.get("a"))
s.close()

增加数据

s.shelve.open("data.dat")
print(s["a"])
s["b"]=[1,2,3,4]
s.close()

删除数据:del s["a"]

修改数据:s["a"]=[1,2,3,4]

shutil模块

shutil.copyfileobj(fsrc,fdst,length=16*1024) -- 复制文件,可指定大小
shutil.copyfile(src,dst) -- 复制文件
shutil.copymode(src,dst) -- 只复制文件权限
shutil.copystat() -- 复制所有状态信息,权限,组等
shutil.copy() -- 复制所有内容及权限
shutil.copy2() --复制所有内容,权限及状态信息
shutil.move(src,dst) -- 递归移动文件
shutil.rmtree() -- 递归删除文件
shutil.copytree() -- 递归copy文件

shutil.make_archive(base_name,format,root_dir,owner,group,logger...)
创建压缩包
base_name:压缩包文件名或路径
format:压缩包类型,如zip,tar,bztar,gztar等
root_dir:要压缩的文件路径,默认当前路径
owner:用户,默认当前用户
logger:记录日志

sympy模块

sys模块

threading模块

https://www.cnblogs.com/i0day/p/9002731.html

from threading import Thread
t = Thread(target=func)

# 启动子线程
t.start()

# 阻塞子线程,待子线程结束后,再往下执行
t.join()

# 判断线程是否在执行状态,在执行返回True,否则返回False
t.is_alive()
t.isAlive()

# 设置线程是否随主线程退出而退出,默认为False
t.daemon = True
t.daemon = False

# 设置线程名
t.name = "My-Thread"

函数创建多线程

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2019-01-23 22:27:22
# @Author  : cdl ([email protected])
# @Link    : https://github.com/cdlwhm1217096231/python3_spider
# @Version : $Id$

import time
from threading import Thread

# 自定义线程函数
def my_threadfunc(name='python3'):
    for i in range(2):
        print("hello", name)
        time.sleep(1)

# 创建线程01,不指定参数
thread_01 = Thread(target=my_threadfunc)
# 启动线程01
thread_01.start()

# 创建线程02,指定参数,注意逗号不要少,否则不是一个tuple
thread_02 = Thread(target=my_threadfunc, args=('Curry',))
# 启动线程02
thread_02.start()

类创建多线程

import time
from threading import Thread
class MyThread(Thread):
    def __init__(self, name='Python3'):
        super().__init__()
        self.name = name

    def run(self):
        for i in range(2):
            print("Hello", self.name)
            time.sleep(1)

控制线程器动与停止

import time
import threading

class DownThread:
    def __init__(self):
        self._running = True

    def terminate(self):
        self._running = False

    def run(self, n):
        while self._running and n > 0:
            print('T-minus', n)
            n -= 1
            time.sleep(1)
  

if __name__=='__main__':

    c = DownThread()
    t = threading.Thread(target=c.run, args=(10,))
    t.start()
    time.sleep(3)
    c.terminate()
    t.join()

tkinter模块

Tkinter(即 tk interface,简称“Tk”)本质上是对 Tcl/Tk 软件包的 Python 接口封装,它是 Python 官方推荐的 GUI 工具包,属于 Python 自带的标准库模块,当您安装好 Python 后,就可以直接使用它,而无须另行安装。

作为一款 Python  GUI 工具,Tkinter 拥有良好的跨平台性,支持 Windows、Linux、Mac 平台,它传承了 Python 语法简洁、代码易读的基本特点。

与其他编程语言的 GUI 工具包相比,Tkinter 编码效率高,能够实现快速开发的目的,非常适合初学者学习。Tkinter 使用纯 Python 语言开发,与 C/C++ 开发的 Qt 框架相比,Tkinter 有自身的局限性,比如性能、功能丰富程度等都不及 Qt,因此它只适合开发一些简单的程序

创建窗口

import tkinter
# 实例化
top=tkinter.Tk()
# 进入消息循环
top.mainloop()

窗口属性和方法

标题:title

图标:iconbitmap

大小:geometry

长宽可变:resizable

获取显示器宽度:winfo_screenwidth

获取显示器高度:winfo_screenheight

Windows无边框全屏:overrideredirect

配置:configure,参数较多,使用configure().keys()查看所有参数

import tkinter
# 实例化
top=tkinter.Tk()

top.title('Hacker Tools')
top.iconbitmap('a9.ico')
# 全屏显示(默认有偏移,所以需要指定偏移量为0,+代表向下或向右,-代表向上或向左)
top.geometry(str(top.winfo_screenwidth())+'x'+str(top.winfo_screenheight())+'+0+0')
#top.resizable(width=True,height=True)
# 简单设置方法
#top.resizable(0,0)
top.overrideredirect(True)
#top.overrideredirect(1)
# 设置背景颜色
top.configure(background = 'black')
# 进入消息循环
top.mainloop()

组件

按钮组件

画布控件

canvas = tkinter.Canvas()

import tkinter
# 实例化
top=tkinter.Tk()
top.title('Hacker Tools')
# 创建画布,bd为边框宽度,highlightthickness=0会消除边框白色
canvas = tkinter.Canvas(top,width=top.winfo_screenwidth(),height=top.winfo_screenheight(),bd=0,highlightthickness=0)
photo=tkinter.PhotoImage(file='bg.png')
#设置背景图,前两个参数为偏移量
canvas.create_image(top.winfo_screenwidth()/2,top.winfo_screenheight()/2,image=photo)
canvas.pack()
top.mainloop()

标签控件

lb = tkinter.Label()

import tkinter
# 实例化
top=tkinter.Tk()
top.title('Hacker Tools')
photo=tkinter.PhotoImage(file='bg.png')
# text为标签内容,justify为内容对齐方式,fg为前景色,font为字体
lb=tkinter.Label(top,text="文字",justify=tkinter.CENTER,fg="green",image=photo,compound=tkinter.CENTER)
lb.pack()
# 进入消息循环
top.mainloop()

输入控件

e = tkinter.Entry()

import tkinter
# 实例化
top=tkinter.Tk()
# 创建文本框
e=tkinter.Entry(top,font=('Times',14),bg='black',fg='#00ff00',highlightthickness=1)
# 布局
e.place(relx=0.33,rely=0.53,width=top.winfo_screenwidth()/3, height=top.winfo_screenheight()/30)

# 进入消息循环
top.mainloop()

布局管理

pack属性

fill:填充设置,fill = X(水平方向填充)fill = Y(垂直方向填充)fill = BOTH(水平和垂直)NONE 不填充

side:对齐方式,left,top,right,bottom,如pack(side='top')

ipadx:子组件X轴偏移量,单位为像素

ipady:子组件Y轴偏移量,单位为像素

padx:X轴偏移量,单位为像素

pady:Y轴偏移量,单位为像素

place属性

x、y:组件偏移量,单位为像素

relx、rely:组件偏移量,值为0~1的浮点数

width:组件的宽度,单位为像素

height:组件高度,单位为像素

relwidth、relheight:组件宽、高,取值0~1的浮点数

urllib模块

https://www.cnblogs.com/zhangxinqi/p/9170312.html

python3对urllib和urllib2进行了重构,将urllib库和urilib2库合并成了urllib库,将urllib2模块分成了:,这样的架构从逻辑和结构上说更加合理。urllib库无需安装,python3自带。

  1. urllib.request:基本的http请求模块,用来模拟发送请求
  2. urllib.robotparser:主要用来识别网站的robots.txt文件,然后判断哪些网站可以爬
  3. urllib.parse:一个工具模块,提供了许多URL处理方法,如:拆分、解析、合并等
  4. urllib.error:异常处理模块,如果出现错误可以捕获这些异常

urllib2.urlopen() 变成了 urllib.request.urlopen()urllib2.Request() 变成了urllib.request.Request(),python2中的 cookielib 改为 http.cookiejarurljoin对应的函数是urllib.parse.urljoin

  • urllib.request.urlopen函数
    返回一个HTTPResponse类型的对象,包含的方法和属性:
    方法:read()readinto()getheader(name)getheaders()fileno()
    属性:msgversionstatusreasonbebuglevelclosed
    代码示例:
    函数参数
    url:网站地址,str类型,也可以是一个request对象
    data:data参数是可选的,内容为字节流编码格式的即bytes类型,如果传递data参数,urlopen将使用Post方式请求
    timeout参数:用于设置超时时间,单位为秒,如果请求超出了设置时间还未得到响应则抛出异常,支持HTTP,HTTPS,FTP请求
    context:必须是ssl.SSLContext类型,用来指定SSL设置,此外,cafilecapath这两个参数分别指定CA证书和它的路径,会在https链接时用到
    代码示例:
import urllib.request
#请求站点获得一个HTTPResponse对象
response=urllib.request.urlopen('https://www.python.org')
#print(response.read().decode('utf-8'))   #返回网页内容
#print(response.getheader('server')) #返回响应头中的server值
#print(response.getheaders()) #以列表元祖对的形式返回响应头信息
#print(response.fileno()) #返回文件描述符
#print(response.version)  #返回版本信息
#print(response.status)  #返回状态码200,404代表网页未找到
#print(response.debuglevel) #返回调试等级
#print(response.closed)  #返回对象是否关闭布尔值
#print(response.geturl()) #返回检索的URL
#print(response.info()) #返回网页的头信息
#print(response.getcode()) #返回响应的HTTP状态码
#print(response.msg)  #访问成功则返回ok
#print(response.reason) #返回状态信息
from urllib.request import urlopen
import urllib.parse
data = bytes(urllib.parse.urlencode({'word':'hello'}),encoding='utf-8') 
#data需要字节类型的参数,使用bytes()函数转换为字节,使用urllib.parse模块里的urlencode()方法来讲参数字典转换为字符串并指定编码
response = urlopen('http://httpbin.org/post',data=data)
print(response.read())
#output
b'{
"args":{},
"data":"",
"files":{},
"form":{"word":"hello"},  #form字段表明模拟以表单的方法提交数据,post方式传输数据
"headers":{"Accept-Encoding":"identity",
    "Connection":"close",
    "Content-Length":"10",
    "Content-Type":"application/x-www-form-urlencoded",
    "Host":"httpbin.org",
    "User-Agent":"Python-urllib/3.5"},
"json":null,
"origin":"114.245.157.49",
"url":"http://httpbin.org/post"}\n'
import urllib.request
response=urllib.request.urlopen('http://httpbin.org/get',timeout=0.1)  #设置超时时间为0.1秒,将抛出异常
print(response.read())

#output
urllib.error.URLError: <urlopen error timed out>

#可以使用异常处理来捕获异常
import urllib.request
import urllib.error
import socket
try:
    response=urllib.request.urlopen('http://httpbin.org/get',timeout=0.1)
    print(response.read())
except urllib.error.URLError as e:
    if isinstance(e.reason,socket.timeout): #判断对象是否为类的实例
        print(e.reason) #返回错误信息
#output
timed out
  • urllib.request.Requset函数
    函数参数
    url:请求的URL,必须传递的参数,其他都是可选参数
    data:上传的数据,必须传bytes字节流类型的数据,如果它是字典,可以先用urllib.parse模块里的urlencode()编码
    headers:它是一个字典,传递的是请求头数据,可以通过它构造请求头,也可以通过调用请求实例的方法add_header()来添加
    例如:修改User_Agent头的值来伪装浏览器,比如火狐浏览器可以这样设置:
    {'User-Agent':'Mozilla/5.0 (compatible; MSIE 5.5; Windows NT)'}
    origin_req_host:指请求方的host名称或者IP地址
    unverifiable:表示这个请求是否是无法验证的,默认为False,如我们请求一张图片如果没有权限获取图片那它的值就是true
    method:是一个字符串,用来指示请求使用的方法,如:GET,POST,PUT等
    代码示例:
#!/usr/bin/python3
#coding:utf8
from urllib import request,parse

url='http://httpbin.org/post'
headers={
    'User-Agent':'Mozilla/5.0 (compatible; MSIE 5.5; Windows NT)',
    'Host':'httpbin.org'
}  #定义头信息

dict={'name':'germey'}
data = bytes(parse.urlencode(dict),encoding='utf-8')
req = request.Request(url=url,data=data,headers=headers,method='POST')

#也可以request的方法来添加
#req.add_header('User-Agent','Mozilla/5.0 (compatible; MSIE 8.4; Windows NT') 
response = request.urlopen(req) 
print(response.read())
  • urllib.request的高级类
    urllib.request模块里的BaseHandler类,他是所有其他Handler的父类,他是一个处理器,比如用它来处理登录验证,处理cookies,代理设置,重定向等。它提供了直接使用和派生类使用的方法:
    add_parent(director):添加director作为父类
    close():关闭它的父类
    parent():打开使用不同的协议或处理错误
    defautl_open(req):捕获所有的URL及子类,在协议打开之前调用
    Handler的子类包括:
    HTTPDefaultErrorHandler:用来处理http响应错误,错误会抛出HTTPError类的异常
    HTTPRedirectHandler:用于处理重定向
    HTTPCookieProcessor:用于处理cookies
    ProxyHandler:用于设置代理,默认代理为空
    HTTPPasswordMgr:永远管理密码,它维护用户名和密码表
    HTTPBasicAuthHandler:用户管理认证,如果一个链接打开时需要认证,可以使用它来实现验证功能
    OpenerDirector类是用来处理URL的高级类,它分三个阶段来打开URL:
    在每个阶段中调用这些方法的顺序是通过对处理程序实例 进行排序来确定的;每个使用此类方法的程序都会调用protocol_request()方法来预处理请求,然后调用protocol_open()来处理请求,最后调用protocol_response()方法来处理响应。
    之前的urlopen()方法就是urllib提供的一个Opener,通过Handler处理器来构建Opener实现Cookies处理,代理设置,密码设置等
    Opener的方法包括:
    add_handler(handler):添加处理程序到链接中
    open(url,data=None[,timeout]):打开给定的URL与urlopen()方法相同
    error(proto,*args):处理给定协议的错误
    密码验证代码示例:
    代理设置代码示例:
    获取Cookie代码示例:
from urllib.request import HTTPPasswordMgrWithDefaultRealm,HTTPBasicAuthHandler,build_opener
from urllib.error import URLError

username='username'
passowrd='password'
url='http://localhost'
p=HTTPPasswordMgrWithDefaultRealm() #构造密码管理实例
p.add_password(None,url,username,passowrd) #添加用户名和密码到实例中
auth_handler=HTTPBasicAuthHandler(p) #传递密码管理实例构建一个验证实例
opener=build_opener(auth_handler)  #构建一个Opener
try:
    result=opener.open(url)  #打开链接,完成验证,返回的结果是验证后的页面内容
    html=result.read().decode('utf-8')
    print(html)
except URLError as e:
    print(e.reason)
from urllib.error import URLError
from urllib.request import ProxyHandler,build_opener

proxy_handler=ProxyHandler({
    'http':'http://127.0.0.1:8888',
    'https':'http://127.0.0.1:9999'
})
opener=build_opener(proxy_handler) #构造一个Opener
try:
    response=opener.open('https://www.baidu.com')
    print(response.read().decode('utf-8'))
except URLError as e:
    print(e.reason)
import http.cookiejar,urllib.request
cookie=http.cookiejar.CookieJar() #实例化cookiejar对象
handler=urllib.request.HTTPCookieProcessor(cookie) #构建一个handler
opener=urllib.request.build_opener(handler) #构建Opener
response=opener.open('http://www.baidu.com') #请求
print(cookie)
for item in cookie:
    print(item.name+"="+item.value)
  • urllib.parse.unquote
    URL解码函数
  • urllib.parse.quote
    URL编码,不编码&$等保留字
  • urllib.parse.quote_plus
    URL编码所有

websockets模块

WebSocket服务器的方法:

  1. websockets.serve(handler, host, port, **kwargs): 创建一个WebSocket服务器对象,需要提供处理客户端连接的处理函数handler,以及服务器的主机名host和端口号port

    • handler: 处理客户端连接的异步函数
    • host: 服务器的主机名或IP地址。
    • port: 服务器的端口号。
    • **kwargs: 其他参数,例如SSL配置等。一些常见的参数包括:

      • ssl: 用于启用SSL/TLS加密连接的配置。通常需要传递一个SSLContext对象。示例:ssl=context,其中context是一个已经配置好的SSLContext对象。
      • ping_interval: 定义发送ping帧的时间间隔(以秒为单位)。如果WebSocket服务器需要定期检查客户端的连接状态,可以使用此参数。示例:ping_interval=5,表示每隔5秒发送一次ping帧。
      • ping_timeout: 定义等待pong帧的超时时间(以秒为单位)。如果在此时间内未收到pong帧,则认为连接已断开。示例:ping_timeout=10,表示等待pong帧的超时时间为10秒。
      • compression: 定义是否启用消息压缩。可以设置为None(默认)、deflate或者其他压缩算法的名称。示例:compression="deflate",表示启用deflate压缩算法。
      • max_size: 定义接收消息的最大大小(以字节为单位)。如果消息超过此大小,服务器将拒绝接收。示例:max_size=65536,表示接收消息的最大大小为64KB。
      • max_queue: 定义等待处理的最大连接队列大小。如果连接队列已满,新的连接请求将被拒绝。示例:max_queue=100,表示等待处理的最大连接队列大小为100。
      • read_limit: 定义每次读取数据的最大字节数。如果接收的数据超过此限制,服务器将关闭连接。示例:read_limit=8192,表示每次读取数据的最大字节数为8KB。
      • write_limit: 定义每次发送数据的最大字节数。如果发送的数据超过此限制,服务器将关闭连接。示例:write_limit=8192,表示每次发送数据的最大字节数为8KB。
      • create_protocol: 定义创建WebSocket协议对象的函数。通常情况下,您不需要手动指定此参数,除非您希望自定义创建协议的行为。
  2. serve_forever(): 启动WebSocket服务器,使其永久运行,接受并处理客户端连接。
  3. close(): 关闭WebSocket服务器,停止监听新的连接请求。

WebSocket 服务端属性:

  1. remote_address: 返回客户端的地址信息。
  2. request_headers: 返回客户端的请求头信息。
  3. connections: 表示当前连接到服务器的所有客户端连接列表。
  4. max_connections: 表示服务器允许的最大连接数。
  5. is_serving: 表示服务器是否正在运行。

WebSocket客户端的方法:

  1. websockets.connect(uri, **kwargs): 创建一个WebSocket客户端对象,连接到指定的WebSocket服务器。

    • uri: WebSocket服务器的URI,例如ws://localhost:8765
    • **kwargs: 其他参数,例如SSL配置等。一些常见的参数包括:

      • ssl: 如果您需要通过 SSL/TLS 连接到 WebSocket 服务器,可以设置为一个 SSLContext 对象,用于配置加密连接。
      • proxy: 如果您需要使用代理服务器来连接 WebSocket 服务器,可以设置为一个代理服务器的 URL。
      • origin: 指定客户端的起源 (Origin),通常用于浏览器中的跨域请求。
      • subprotocols: 指定客户端支持的子协议列表,用于在 WebSocket 握手中提供给服务器选择。
      • extra_headers: 传递额外的 HTTP 请求头给服务器,通常用于进行认证或者传递其他信息。
      • ping_interval: 设置客户端发送 ping 消息的间隔时间。
      • ping_timeout: 设置客户端等待服务器响应 ping 消息的超时时间。
      • close_timeout: 设置关闭连接的超时时间,用于等待服务器发送关闭帧。
  2. send(data): 向WebSocket服务器发送数据。

    • data: 要发送的数据,通常为字符串或字节。
  3. recv(): 从WebSocket服务器接收数据。
  4. ping(data): 向WebSocket服务器发送ping帧。
  5. pong(data): 向WebSocket服务器发送pong帧。
  6. close(code=None, reason=None): 关闭WebSocket连接。

    • code: 关闭代码(可选)。
    • reason: 关闭原因(可选)。
  7. local_address: 本地地址(只读属性)。
  8. remote_address: 远程地址(只读属性)。
  9. state: 连接状态,表示连接是否已经建立。
  10. subprotocol: 使用的子协议(只读属性)。

WebSocket 客户端属性:

  1. local_address: 返回客户端的本地地址信息。
  2. remote_address: 返回服务器端的地址信息。
  3. response_headers: 返回服务器端的响应头信息。
  4. state: 表示客户端连接的状态。
  5. subprotocol: 表示客户端和服务器之间所使用的子协议。

示例代码

模拟一对一通信,客户端发送消息给服务端,服务端返回客户端的消息。

服务端:

import asyncio
import websockets

async def handle_client(websocket, path):
    # 获取客户端的地址信息
    remote_addr = websocket.remote_address
    print(f"客户端 {remote_addr} 已连接")

    # 获取客户端的请求头信息
    request_headers = websocket.request_headers
    print("请求头信息:",request_headers)
    async for message in websocket:
        print("接收到消息:",message)
        # 发送消息到客户端
        await websocket.send(message)

async def main():
    # 创建 WebSocket 服务器,并启动
    server = await websockets.serve(handle_client, "localhost", 8765)
    print("WebSocket 服务已启动, 真正监听端口 8765...")

    # 永久运行服务器,直到收到键盘中断信号
    await server.serve_forever()

# 运行主程序
asyncio.run(main())

客户端:

import websockets
import asyncio

async def main():
    # 连接到 WebSocket 服务器
    async with websockets.connect("ws://localhost:8765") as websocket:
        while True:
            print(websocket.remote_address)
            print(websocket.response_headers)
            # 输入消息并发送给服务器
            message = input("请输入要发送的消息: ")
            await websocket.send(message)
            print("消息已发送")
            
            # 接收服务器返回的消息
            response = await websocket.recv()
            print(f"接收到服务端的消息: {response}")

# 运行主程序
if __name__ == "__main__":
    asyncio.run(main())

运行结果:

xlrd模块

import xlrd

# 设置路径
path = 'E:/input.xlsx'
# 打开execl
workbook = xlrd.open_workbook(path)

# 输出Excel文件中所有sheet的名字
print(workbook.sheet_names())

# 根据sheet索引或者名称获取sheet内容
Data_sheet = workbook.sheets()[0]  # 通过索引获取
# Data_sheet = workbook.sheet_by_index(0)  # 通过索引获取
# Data_sheet = workbook.sheet_by_name(u'名称')  # 通过名称获取


print(Data_sheet.name)  # 获取sheet名称
rowNum = Data_sheet.nrows  # sheet行数
colNum = Data_sheet.ncols  # sheet列数

# 获取所有单元格的内容
list = []
for i in range(rowNum):
    rowlist = []
    for j in range(colNum):
        rowlist.append(Data_sheet.cell_value(i, j))
    list.append(rowlist)
# 输出所有单元格的内容
for i in range(rowNum):
    for j in range(colNum):
        print(list[i][j], '\t\t', end="")
    print()

# 获取整行和整列的值(列表)
rows = Data_sheet.row_values(0)  # 获取第一行内容
cols = Data_sheet.col_values(1)  # 获取第二列内容
# print (rows)
# print (cols)

# 获取单元格内容
cell_A1 = Data_sheet.cell(0, 0).value
cell_B1 = Data_sheet.row(0)[1].value  # 使用行索引
cell_C1 = Data_sheet.cell(0, 2).value
cell_D2 = Data_sheet.col(3)[1].value  # 使用列索引
print(cell_A1, cell_B1, cell_C1, cell_D2)

# 获取单元格内容的数据类型
# ctype:0 empty,1 string, 2 number, 3 date, 4 boolean, 5 error
print('cell(0,0)数据类型:', Data_sheet.cell(0, 0).ctype)
print('cell(1,0)数据类型:', Data_sheet.cell(1, 0).ctype)
print('cell(1,1)数据类型:', Data_sheet.cell(1, 1).ctype)
print('cell(1,2)数据类型:', Data_sheet.cell(1, 2).ctype)

# 获取单元格内容为日期的数据
date_value = xlrd.xldate_as_tuple(Data_sheet.cell_value(1,0),workbook.datemode)
print(type(date_value), date_value)
print('%d:%d:%d' % (date_value[0:3]))

xml模块

1、字符串解析

利用ElementTree.XML将字符串解析成xml对象,示例代码:

import xml.etree.ElementTree as ET

# 定义一个 XML 字符串
xml_string = """
<root>
    <person>
        <name>John</name>
        <age>30</age>
    </person>
    <person>
        <name>Alice</name>
        <age>25</age>
    </person>
</root>
"""

# 使用 ElementTree 解析 XML 字符串
root = ET.fromstring(xml_string)

# 遍历解析后的 XML 数据
for person in root.findall('person'):
    name = person.find('name').text
    age = person.find('age').text
    print(f"Name: {name}, Age: {age}")

这种方法也可以利用在requests请求后,返回来的xml结果集。

2、文本文件直接解析

利用ElementTree.parse将文件直接解析成xml对象。示例代码:

import xml.etree.ElementTree as ET

# 使用 ElementTree.parse() 解析 XML 文件
tree = ET.parse('example.xml')

# 获取根节点
root = tree.getroot()

# 遍历 XML 树结构
for child in root:
    print(child.tag, child.attrib)
    for sub_child in child:
        print("\t", sub_child.tag, sub_child.text)

z3模块

安装

pip install z3_solver

使用

z3中有3种类型的变量,分别是整型(Int),实型(Real)和向量(BitVec)。

对于整数类型数据,基本API:

  1. Int(name, ctx=None),创建一个整数变量,name是名字
  2. Ints (names, ctx=None),创建多个整数变量,names是空格分隔名字
  3. IntVal (val, ctx=None),创建一个整数常量,有初始值,没名字。

对于实数类型的API与整数类型一致,向量(BitVec)则稍有区别:

  1. Bitvec(name,bv,ctx=None),创建一个位向量,name是他的名字,bv表示大小
  2. BitVecs(name,bv,ctx=None),创建一个有多变量的位向量,name是名字,bv表示大小
  3. BitVecVal(val,bv,ctx=None),创建一个位向量,有初始值,没名字。

simplify(表达式),对可以简化的表达式进行简化。

import z3
x=z3.Int('x')
y=z3.Int('y')
z3.solve(x >2,y<10,x+2*y==7)

https://developer.aliyun.com/article/815127

https://ericpony.github.io/z3py-tutorial/guide-examples.htm

如果需要取出指定变量的结果,可以使用Solver求解器:

  1. s=Solver(),创建一个解的对象。
  2. s.add(条件),为解增加一个限制条件
  3. s.check(),检查解是否存在,如果存在,会返回"sat"
  4. modul(),输出解得结果
x,y=z3.Ints('x y')
s=z3.Solver()
s.add(x>2)
s.add(y<10)
s.add(x+2*y==7)
if s.check() == z3.sat:
  res=s.model()
  print(res)
else:
  print('unsat')

一些问题

增加限制条件的时候发现,添加逻辑运算符不生效,使用or时,仅判断右边的表达式,使用and时,仅判断了左边的表达式

python_adb_utils模块

安装

你可以通过pip安装这个软件包 pip install python_adb_utils

pip3 install python_adb_utils

用法:

要使用这些工具,只需导入并创建adbutils()的实例即可

from adb_utils import adb_utils as adb

adb.get_connected_devices()

示例代码

import subprocess
import os


def get_connected_devices() -> list:
    """
    Returns a list of tuples containing the Device name and the android Version
    :return:
    """
    devices = []
    devices_output = subprocess.check_output(["adb", "devices"]).decode("utf-8").strip("List of devices attached").split("\n")
    for device in devices_output:
        if device is None or device == "":
            pass
        else:
            device_name = device.strip('\tdevice')
            android_version = subprocess.check_output(["adb", "-s", device_name, "shell", "getprop", "ro.build.version.release"])
            devices.append((device_name, android_version.decode('utf-8').strip("\r\n")))

    return devices


def install_app(apk_path=None, device=None) -> bool:
    """
    Installs an APK file into a device.
    The app installed with the -r option so the apk gets replaced it exists or installed if it doenst
    :param apk_path: Path for the APK
    :param device:   Device name
    :return: True if success , False if fail
    """
    path = os.getcwd() + apk_path if str(apk_path).startswith("/") else os.getcwd() + "/" + apk_path

    if apk_path is not None and device is not None:
        if os.path.isfile(path):
            command = ["adb", "-s" , device, "install", "-r", path]
            p = subprocess.Popen(command, stdout=None)
            p.wait()
            p.terminate()
            print("APK {0} was installed in {1}".format(apk_path, device))
            return True
        else:
            print("File {0} not found!".format(path))

    else:
        print("Device and/or apk not found or not specified")
        return False


def is_device_connected(device) -> bool:
    all_connected = get_connected_devices()
    for device_connected, version in all_connected:
        if device == device_connected:
            return True
    return False


def unintall_app(package=None, device=None) -> None:
    """
    Uninstall an app from the device
    :return:
    """
    command = ["adb", "-s", device, "uninstall", package]

    if package is not None:
        if device is None:
            command.pop(1)
            command.pop(1)

        p = subprocess.Popen(command, stdout=None)
        p.wait()
        p.terminate()
    else:
        print("App package was not specified.")


def is_app_installed(package=None, device=None) -> bool:
    """
    Returns True if the package is installed or False if it is not
    :param package:
    :return:
    """
    command = ["adb", "-s", device, "shell", "pm", "list", "packages |", "grep", package]

    if device is None:
        command.pop(1)
        command.pop(1)

    out = subprocess.check_output(command, stderr=None)

    return True if out.decode('utf-8').strip("\r\n") == "package:{0}".format(package) else False


def run_command(arg_string=None, arg_list=None) -> None:
    """
    Run a general ABD command
    :return:
    """
    command = arg_list if arg_list else str(arg_string).split(" ")

    p = subprocess.check_output(command, stderr=None)
    print(p.decode('utf-8'))


def kill_server() -> None:
    """
    Kills the ADB server
    :return: None
    """
    command = ["adb", "kill-server"]

    p = subprocess.Popen(command, stdout=None, stderr=None)
    p.wait(timeout=10)
    print("ADB server has been killed.")


def start_server() -> None:
    """
    Starts the ADB server
    :return: None
    """
    command = ["adb", "start-server"]

    p = subprocess.Popen(command, stderr=None, stdout=None)
    p.wait(timeout=10)
    print("ADB server has been started.")


def get_apk_from_device(package=None, device=None) -> bool:
    """
    Retrieves the APK of an application if it exists
    :param package:
    :param device:
    :return: bool
    """

    # adb shell pm path com.example.someapp
    # adb pull /data/app/com.example.someapp-2.apk path/to/desired/destination

    command_apk_path = ["adb", "-s", device, "pm", "path", package]

    if package is None:
        print("Package is required but it was not specified.")
        return False

    if device is None and len(get_connected_devices()) != 1:
        print("There are multiple devices connected, please specify a device to get the APK from")
        return False

    elif device is None:
        command_apk_path.pop(1)
        command_apk_path.pop(1)

    apk_path = subprocess.check_output(command_apk_path, stderr=None)

    # TODO: Rest of the stuff


def push_file_to_device() -> None:  # For now...
    """
    Pushes a file to the device
    :param device:
    :return: None
    """
    pass


def list_files_in_device() -> None:
    """
    Gets a list of files in a specific folder
    :param device:
    :param path:
    :return: list of files
    """
    pass


def unlock_device(password=None, device=None) -> bool:
    """
    Unlocks a device given a device name and the password
    :param password:
    :param device:
    :return: True is sucess, False if error
    """
    command_input = ["adb", "-s", device, "shell", "input", "text", str(password), "&&", "adb", "-s", device, "shell", "input", "keyevent", "66"]

    if device is None and len(get_connected_devices()) != 1:
        print("No device was specified and/or multiple devices are connected")
        return False

    if device is None:
        print("Device was not specified.")
        return False

    p = subprocess.Popen(command_input)
    p.wait()

    return True

pandas模块

简介

Pandas 是一个强大灵活的数据分析工具,构建在 NumPy 的基础上,提供了一种快速、灵活、表达力强的数据结构,特别是 DataFrame,使得数据的清洗、转换、分析等工作变得更加简单和高效。下面是 Pandas 模块的一些主要特点和功能:

主要特点

  1. DataFrame 和 Series 数据结构:Pandas 提供了 DataFrameSeries 两种主要的数据结构。DataFrame 类似于电子表格或 SQL 表,由行和列组成,可用于存储异构数据。Series 是一维标签数组,可存储同质数据。
  2. 灵活的数据索引:Pandas 允许使用标签对数据进行索引和切片,同时也支持位置索引。
  3. 数据对齐和缺失值处理:Pandas 的操作会自动对齐不同索引的数据,如果某些数据缺失,可以灵活处理,如填充、删除等。
  4. 强大的数据操作和处理功能:Pandas 提供了丰富的函数和方法,用于数据的重塑、切片、筛选、合并、排序、分组、聚合等操作,以及对时间序列数据的处理。
  5. IO 工具:Pandas 提供了丰富的 IO 工具,支持多种数据格式的读写,如 CSV、Excel、SQL 数据库、JSON、HTML 等。
  6. 灵活的数据可视化功能:Pandas 结合了 Matplotlib 库,提供了简单易用的绘图功能,可以轻松地对数据进行可视化分析。

常用功能

  1. 数据读取和写入:使用 pd.read_xxx() 函数读取各种格式的数据文件,如 CSV、Excel、SQL 数据库等;使用 DataFrame.to_xxx() 方法将数据写入到文件中。
  2. 数据清洗和处理:包括处理缺失值、重复值、异常值、数据转换、数据合并、数据重塑等操作。
  3. 数据分析和统计:包括描述性统计、数据筛选、分组和聚合、透视表等分析功能。
  4. 数据可视化:使用 DataFrame.plot() 方法进行简单的数据可视化,或者结合 Matplotlib、Seaborn 等库进行更复杂的数据可视化。
  5. 时间序列分析:Pandas 提供了丰富的时间序列处理功能,包括日期索引、日期范围生成、频率转换、滑动窗口等。
  6. 高性能运算:Pandas 基于 NumPy 实现,拥有高效的数据处理和运算能力,可以处理大规模数据集。

常用方法

以下是 Pandas 中一些常用的函数和方法:

数据结构:

  1. pd.DataFrame(data, index, columns): 创建一个数据框(DataFrame)对象,用于存储二维数据。
  2. pd.Series(data, index): 创建一个序列(Series)对象,用于存储一维数据。

数据导入和导出:

  1. pd.read_csv(): 从 CSV 文件中读取数据到 DataFrame。
  2. pd.read_excel(): 从 Excel 文件中读取数据到 DataFrame。
  3. pd.to_csv(): 将 DataFrame 数据写入到 CSV 文件。
  4. pd.to_excel(): 将 DataFrame 数据写入到 Excel 文件。

数据清洗和转换:

  1. DataFrame.head(n): 返回前 n 行数据。
  2. DataFrame.tail(n): 返回后 n 行数据。
  3. DataFrame.info(): 显示 DataFrame 的基本信息。
  4. DataFrame.describe(): 显示 DataFrame 的统计摘要。
  5. DataFrame.dropna(): 删除包含缺失值的行或列。
  6. DataFrame.fillna(value): 填充缺失值。
  7. DataFrame.drop_duplicates(): 删除重复行。
  8. DataFrame.apply(func): 对 DataFrame 的行或列应用函数。

数据选择和操作:

  1. DataFrame.loc[]: 通过标签选择行或列。
  2. DataFrame.iloc[]: 通过位置选择行或列。
  3. DataFrame[column_name]DataFrame.column_name: 通过列名选择列。
  4. DataFrame[[col1, col2, ...]]: 选择多列。
  5. DataFrame.query(): 使用表达式查询数据。
  6. DataFrame.groupby(): 按照某一列分组。
  7. DataFrame.merge(): 合并两个 DataFrame。

数据分析和统计:

  1. DataFrame.mean(): 计算平均值。
  2. DataFrame.median(): 计算中位数。
  3. DataFrame.std(): 计算标准差。
  4. DataFrame.corr(): 计算相关系数矩阵。
  5. DataFrame.value_counts(): 统计唯一值的频数。
  6. DataFrame.groupby().agg(): 对分组后的数据进行聚合计算。

数据可视化:

  1. DataFrame.plot(): 绘制数据图表。
  2. DataFrame.hist(): 绘制直方图。
  3. DataFrame.boxplot(): 绘制箱线图。
  4. DataFrame.plot.scatter(): 绘制散点图。

其它

压缩与解压缩文件

zipfile模块

压缩
  z=zipfile.ZipFile("压缩文件名","w")
  z.write("file")
  z.close()
解压
  z=zipfile.ZipFile("压缩文件名","r")
  z.extractall()
  z.close()

tarfile模块

压缩
t=tarfile.open("xxx.tar","w")
t.add("file")
t.close()
解压
t=tarfile.open("xxx.tar","r")
t.extractall()
t.close()

进制转换

bytes与hex字符串互转

https://www.cnblogs.com/gqv2009/p/12683476.html

全盘扫描

def GetFiles(keywords):
  result=[]
  # 获取磁盘盘符
  pathList=[chr(x) for x in range(65,91)]
  for p in pathList:
    pdir=Path(p+':\\')
    if pdir.exists() and pdir.is_dir():
      #print(p+":\\")
      result+=list(pdir.rglob(keywords))
      return result

print(GetFiles('*.mp3'))
print(GetFiles('abc'))

生成二维码

字符串生成二维码:

import qrcode 
img = qrcode.make('hello, qrcode')
img.save('test.png')

生成微信链接二维码:

img = qrcode.make('weixin://contacts/profile/'+wxid)

反编译

https://github.com/extremecoders-re/pyinstxtractor

获得pyc

执行:
py pyinstxtractor.py aaa.exe

获得py

安装uncompyle6
python3 -m pip install uncompyle6
反编译pyc文件为py文件:
uncompyle6 -o target_exe.py target_exe.pyc
在线反编译pyc:https://ctfever.uniiem.com/tools/pyc-decompiler

声明:Hack All Sec的博客|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - Python3 学习笔记


Hacker perspective for security