python基础Ⅳ(文件操作、模块和包导入、os模块、自定义模块发布与安装、sys模块、time模块、datetime模块、random模块、hashlib模块)

一、文件操作

打开文件

用于打开一个文件,创建并返回一个 file 对象

open(name[, mode[, buffering]])

  • name : 文件名称的字符串值。

  • mode : 打开文件的模式:只读,写入,追加等。这个参数是非强制的,默认文件访问模式为只读

  • buffering : 如果 buffering 的值被设为 0,就不会有寄存。如果 buffering 的值取 1,访问文件时会寄存行。如果将 buffering 的值设为大于 1 的整数,表明了这就是的寄存区的缓冲大小。如果取负值,寄存区的缓冲大小则为系统默认。

模式说明
b二进制模式 (文本文件、视频、音乐等等都可使用该模式) 。
+打开一个文件进行更新 (可读可写)。
r以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
w打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
a打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件进行写入
r+打开一个文件用于读写。文件指针将会放在文件的开头。不能创建文件,注意指针的位置
w+打开一个文件用于读写。如果该文件已存在则打开文件,并删除原来内容,然后在进行读写,注意指针的位置。如果该文件不存在,创建新文件。
rb+以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头,注意指针的位置。
wb+以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除,注意指针的位置。如果该文件不存在,创建新文件。
  • 要注意的是python3的文件默认编码为utf-8,但文件读和写(r|w)的默认编码为gbk
  • 一个我们可读的txt文本包括两个重要部分,一个是文字的编码格式,另一个是文本的读取格式。这两个要一致才可以把二进制翻译成我们可读的txt文件
  • 文本文件才存在行的概念,二进制文件不存在
  • 之所以存在要注意文件的指向的问题是因为文件的读取在python3里面是以流的形式的
  • 要注意open() 里面的encoding默认为gbkencode() 方法里面的 encoding 默认为utf-8

write()
file_obj = open('./test.txt', 'w', encoding='utf-8')	# 打开文件,并把字符的编码与文件的编码方式换为utf-8,默认为gbk
file_obj.write('你好\n')			# 默认的编码为gbk,在这里是utf-8
file_obj.write('世界\n')
file_obj.close()				# 注意要关闭文件,以对文件进行保护
file_obj = open('./test.txt', 'wb+')

file_obj.write('sss你好,撒大大青蛙的'.encode('utf-8'))	# 以utf-8编码对字符串进行编码,获得bytes类型对象
file_obj.close()

①file.read([size]):size指定的话则返回指定字符个数, 未指定则返回整个文件,f.read()读到文件尾时返回""(空字串),且换行符也算字符注意文件指针的指向

②file.readline():返回一行,且这行里面末尾会自动加上换行符(\n),注意文件指针的指向

③file.readlines([size]) :返回包含size行的列表, size 未指定则返回全部行,注意文件指针的指向

④file.readable():判断file对象是否可读,当然对应的也有writable()函数

with上文管理

with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。

with open('./test.txt', 'r', encoding='utf-8') as file_obj:
    print(file_obj.read())

f.close()

关闭文件流通道

文件备份

# 适用于小文件

def copyFile(param):
    file_list = param.split('.')
    new_file = './' + file_list[0] + '_copy.' + file_list[1]
    old_file_obj = open(param, 'r', encoding='utf-8')
    new_file_obj = open(new_file, 'w', encoding='utf-8')
    new_file_obj.write(old_file_obj.read())
    old_file_obj.close()
    new_file_obj.close()
    pass

copyFile('test.txt')
# 适用于大文件

def copyFile(param):
    file_list = param.split('.')
    new_file = './' + file_list[0] + '_copy.' + file_list[1]
    try:
        with open(param, 'r', encoding='utf-8') as old_file_obj, open(new_file, 'w', encoding='utf-8') as new_file_obj:
            while True:
                str_current = old_file_obj.read(1024)
                new_file_obj.write(str_current)
                if len(str_current) < 1024:
                    break
                    pass
                pass
            old_file_obj.close()
            new_file_obj.close()
            pass
        pass
    except Exception as msg:
        print(msg)
        pass
    else:
        print('复制成功')
        pass
    pass

copyFile('test.txt')

文件读取定位

tell()可以获得当前文件指针读取到的字节位置,不过要注意一个汉字对应两个字节

file_obj = open('./test.txt', 'w', encoding='utf-8')	
file_obj.write('888 ni 你好')			# 12个字节
print(file_obj.tell())

file_obj.close()

truncate()

截取文件内的指定字符

file_obj = open('./test.txt', 'r+', encoding='utf-8')
file_obj.truncate(3)		# 截取文件前三个字符
print(file_obj.read())		# 读取文件
file_obj.close()

seek()

用于移动文件指针到指定位置

fileObject.seek(offset[, whence])

  • offset – 偏移量,也就是代表需要移动偏移的字节数
  • whence:可选,默认值为 0。给offset参数一个定义,表示要从哪个位置开始偏移;0代表从文件开头开始算起,1代表从当前位置开始算起,2代表从文件末尾算起。
with open('./test.txt', 'rb') as file_obj:		# with块
	file_obj.seek(2, 0)
    print(file_obj.read(4).decode('gbk'))		# 把读取的二进制使用gbk编码来解释
    print(file_obj.tell())				# 获得当前的指针位置
    file_obj.seek(-2, 1)				# 报错,不可这样使用
    print(file_obj.read(2).decode('gbk'))
    file_obj.seek(-2, 2)				# 报错
    print(file_obj.read(2).decode('gbk'))

    pass

注意:若没有使用二进制读写文件,则seek函数里面的whence只能为0,而其他情况会报错

例如:


with open('./test.txt', 'r') as file_obj: 		# r模式
    file_obj.seek(2, 0)				# 可以执行
    print(file_obj.read(2))
    print(file_obj.tell())
    
    file_obj.seek(-2, 1)				# 报错
    print(file_obj.read(2))
    
    file_obj.seek(-2, 2)				# 报错
    print(file_obj.read(2))
    pass


with open('./test.txt', 'w') as file_obj:		# w模式
    file_obj.seek(2, 0)				# 可以执行
    file_obj.write('11')
    file_obj.seek(-2, 1)				# 报错
    file_obj.write('11')
    file_obj.seek(-2, 2)				# 报错
    file_obj.write('11')

    pass

二、模块和包导入

模块和包的导入

  • 导入一般放在文件最前面
  • from……import……只导入该模块或包中的部分内容或全部内容(*),要注意的是该方式在调用时只能使用默认名,就可能会造成命名冲突
  • 要注意无论使用何种方式导入模块导入模块的全部内容都会被执行。且在通过包导入模块时候会执行该模块和__init__模块
  • 只导入包时只会执行__init__模块,也就意味着无法访问除__init__模块的其他模块
  • 一次程序执行中对相同的内容import导入就只导入一次
import time
print(time.ctime())

from time import ctime			# 推荐使用
print(time.ctime())

from user.models import User	# user为包名,models为模块名,User为模块内的东西

as为模块取别名

注意这里是模块名,而不是函数名

import time as myTime
print(myTime.ctime())

__name__

python的模块既可以被调用,也可以独立运行。而被调用时__name__存储的是py文件名(模块名称),独立运行时存储的是"__main__"。

__all__

它表示一个模块中允许哪些属性可以被导入到别的模块中(如:全局变量,函数,类),所以它是为了限制或者指定能被导入到别的模块的函数,类,全局变量等,如果指定了那么只能是指定的那些可以被导入,没有指定默认就是全部可以导入。

但需要注意的是__all__只影响到了 from <module> import * 这种导入方式,对于 from <module> import <member> 导入和import <module>方式并没有影响,仍然可以从外部导入。

模块搜索路径

当解释器遇到import关键字,会优先搜索当前录下是否有这个名字的模块,所以在模块命名的时候不要与系统中的模块有重名(自定义的文件优先级高);如果当前目录没有,则到环境变量中搜索;如果都找不到,则搜索默认路径,window的第三方模块安装位置在python安装目录下的lib/site-packages/目录下。

包和文件夹

  • 包和文件夹差异不大,只是包内有一个__init__.py文件。也就是说如果在文件夹里面定义一个__init__.py文件文件夹就变成了一个包
  • 一个项目里可有多个包,一个包里面可以放多个模块

包的__init__.py文件

  • __init__模块会在导入包时自动执行,该模块里面一般放一些初始化函数、变量等等,而函数、变量等可通过包名来调用。
  • 它也可配合__all__来使用

模块的循环导入问题

大型的python项目中,需要很多python文件,由于架构不当,可能会出现模块之间的相互导入,而严重的会导致程序崩溃。不过有两种避免方法:①重新架构,代价太大②将导入的语句放到调用的地方以避免导致程序崩溃③使用__name__ 以避免程序逻辑混乱
例如1(下面的程序因循环导入模块而导致程序崩溃):

# 该文件为index.py
from hello import foo1
def foo():
    print('index---- foo')


# 该文件为hello.py,且为入口文件
from index import foo
def foo1():
    print('hello---- foo1')
foo1()


# 输出结果
ImportError: cannot import name 'foo' from partially initialized module 'index' (most likely due to a circular import)

下面为解决方法:

# 该文件为index.py
def foo():
	from hello import foo1
    print('index---- foo')


# 该文件为hello.py,且为入口文件
from index import foo
def foo1():
    print('hello---- foo1')
foo1()


# 输出结果
hello---- foo1

例如2(下面的程序因多次导入模块而导致程序逻辑混乱):

# 该文件为index.py
def foo():
    print('index---- foo')
    from hello import foo1
    foo1()


# 该文件为hello.py,且为入口文件
from index import foo
def foo1():
    print('hello---- foo1')
def foo2():
    print('hello---- foo2')
    foo()
foo1()
foo2()


# 输出结果
hello---- foo1
hello---- foo2
index---- foo
hello---- foo1
hello---- foo2
index---- foo
hello---- foo1
hello---- foo1

下面为解决方法:

# 该文件为index.py
def foo():
    print('index---- foo')
    from hello import foo1
    foo1()


# 该文件为hello.py,且为入口文件
from index import foo
def foo1():
    print('hello---- foo1')
def foo2():
    print('hello---- foo2')
    foo()
if __name__ == '__main__':			# 防止循环导入模块
    foo1()
    foo2()


# 输出结果
hello---- foo1
hello---- foo2
index---- foo
hello---- foo1

三、os模块

os模块是提供一些系统级别的操作命令(如:文件重命名等),下面介绍一些常用的方法

路径操作

os.path.isabs()

判断路径是否为绝对路径

import os

print(os.path.isabs(r'C:\Users\12133\Documents\WindowsPowerShell'))		# True
os.path.dirname()

它与getcwd函数类似,获得传入参数的上级目录__file__的值为当前文件的绝对路径

import os

print(os.path.dirname(__file__))	# 这里输出的结果为当前文件的工作目录
print(__file__)

# 输出结果
F:\pycharm\pythonProject
F:\pycharm\pythonProject\index.py
os.getcwd()

用于返回当前文件的上级目录,没有参数

import os
print(os.getcwd())			# F:\pycharm\pythonProject
os.path.abspath()

传入的路径转换为绝对路径

import os

print(os.path.abspath('./index.py'))

# 输出结果
F:\pycharm\pythonProject\index.py
os.path.join()

路径拼接,用于将多个路径组合后返回

import os
path = os.path.join(os.getcwd(), 'hello.txt')	# 目录的拼接,注意这里是path下面的join
print(path)
os.path.split()

路径分割获得文件名,用于将一个路径分割并组成一个元组后再返回

import os
print(os.path.split(r'./index.py'))
print(os.path.split(r'F:\pycharm\pythonProject/index.py'))
# 输出结果
('.', 'index.py')
('F:\\pycharm\\pythonProject', 'index.py')

os.path.splitext()

路径分割获得文件拓展名,用于将一个路径分割并组成一个元组后再返回

import os
print(os.path.splitext(r'./index.py'))
print(os.path.splitext(r'F:\pycharm\pythonProject/index.py'))
# 输出结果
('./index', '.py')
('F:\\pycharm\\pythonProject/index', '.py')
os.path.isdir()&os.path.isfile()

判断是否是目录或文件

import os

with os.scandir('./') as entries:			# 使用with来处理资源访问操作
    for entry in entries:
        if os.path.isdir(entry):			# 判断是否为文件夹
            print('文件夹名:{}'.format(entry))
            pass
        elif os.path.isfile(entry):			# 判断是否为文件
            print('文件名:{}'.format(entry))
        pass

文件操作

os.rename()

修改文件名

import os
os.rename( 'test.txt' , 'tests.txt')
os.remove()

删除文件

import os
os.remove( 'tests.txt ')

os.mkdir()

创建文件夹

import os
os.mkdir('myTest')			# 它只能创建一级目录
os.makedirs('d:/myTest/test')			# 它可以创建多级目录

os.rename()&shutil.rmtree()

删除文件夹,os.rename()只能删除空文件夹,shutil.rmtree()用于删除多级文件夹

import os
os.rmdir('myTest')				# 只能删除空目录

import shutil
shutil.rmtree('d:/myTest')		# 删除多级目录

os.chdir()

切换目录

import os
os.chdir('./venv')				# 切换目录
print(os.getcwd())

os.listdir()&os.scandir()

返回目录所在的文件或文件夹列表,只返回一级目录

import os
print(os.listdir('./'))			# 只打印一级,且返回一个列表

print(os.scandir('./'))			# 返回一个迭代器对象
with os.scandir('./') as fileValue:	# with尽量与资源访问一起使用
    for value in fileValue:
        print(value)			# 只打印一级对象
        pass
    pass

四、自定义模块发布与安装

在python里面,一个模块就是一个python文件。

自定义模块发布

需要发布的模块(simpleCompute.py):

def addition(x, y):
    return x + y


def minus(x, y):
    return x - y


className = '一班'

__all__ = ['addition', 'className']

if __name__ == '__main__':			# 测试时执行
    print('这里是测试用例')
    print('__name__值为%s' % __name__)
    pass

若要发布模块的话,要先创建一个文件夹,再把写好的模块放入到文件夹内,然后再在该文件夹内创建一个setup.py文件,内容如下,然后再在终端内进入该文件夹目录内,输入python setup.py build(构建模块),然后会在该文件夹内生成一个build文件夹,再在该文件夹内输入python setup.py sdist,来生成压缩包并会在该文件夹内生成一个dist文件夹。
当然我们也可使用在该文件内输入tree命令来查看这个文件的目录结构

setup.py文件:

from distutils.core import setup
# name模块名称
# version版本号
# description 描述
# author作者
# py_modules要发布的内容
setup(name="simpleCompute", version="1.0", description=”文件的简单计算模块"", autbor="xMan", py_modules=['simpleCompute'])

自定义模块安装

在pycharm里面的终端里面输入pip install 压缩文件即可安装模块

pip install simpleCompute-1.0.tar.gz

五、sys模块

sys模块为python环境模块

sys.path

导入包的搜索路径

import sys

print(sys.path)
# 输出结果
['F:\\pycharm\\pythonProject', 'F:\\pycharm\\pythonProject', 'F:\\pycharm\\PyCharm 2020.2.3\\plugins\\python\\helpers\\pycharm_display', 'F:\\python\\python39.zip', 'F:\\python\\DLLs', 'F:\\python\\lib', 'F:\\python', 'F:\\pycharm\\pythonProject\\venv', 'F:\\pycharm\\pythonProject\\venv\\lib\\site-packages', 'F:\\pycharm\\PyCharm 2020.2.3\\plugins\\python\\helpers\\pycharm_matplotlib_backend']

sys.version

import sys

print(sys.version)
# 输出结果
3.9.0 (tags/v3.9.0:9cf6752, Oct  5 2020, 15:34:40) [MSC v.1927 64 bit (AMD64)]

六、time模块

time()

返回当前的时间戳(秒),浮点类型

import time

print(time.time())
# 输出结果
1606561264.2610068

sleep()

休眠一段时间

import time

print(time.time())
time.sleep(3)
print(time.time())
# 输出结果
1606561596.5063899
1606561599.5070715

ctime()

有参数(时间戳)则把参数转成字符串(该格式无法修改),若无参数返回当前日期(字符串类型)

import time

second = time.time()
print(time.ctime(second))
print(time.ctime())
# 输出结果
Sat Nov 28 19:09:59 2020
Sat Nov 28 19:09:59 2020

strptime()

time.strptime(string, format)

字符串转换为元组类型

import time

print(time.strptime('2020年10月19日', '%Y年%m月%d日'))
# 输出结果
time.struct_time(tm_year=2020, tm_mon=10, tm_mday=19, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=0, tm_yday=293, tm_isdst=-1)

localtime()

time.localtime([ sec ])

有参数(时间戳)则把参数转成元组时间,若无参数则返回当前日期(元组类型)

import time

second = time.time()
print(time.localtime(second))		# 
print(time.localtime())
# 输出结果
time.struct_time(tm_year=2020, tm_mon=11, tm_mday=28, tm_hour=19, tm_min=12, tm_sec=11, tm_wday=5, tm_yday=333, tm_isdst=0)
time.struct_time(tm_year=2020, tm_mon=11, tm_mday=28, tm_hour=19, tm_min=12, tm_sec=11, tm_wday=5, tm_yday=333, tm_isdst=0)

mktime()

元组时间转换为时间戳(浮点型)

import time

time_tuple = time.localtime()
print(time.mktime(time_tuple))
# 输出结果
1606562577.0

strftime()

time.strftime(format[, t])

元组时间转成字符串(该格式可以自定义)

import time

time_tuple = time.localtime()
print(time.strftime('%Y年%m月%d日'))
print(time.strftime('%Y年%m月%d日', time_tuple))
# 输出结果
2020112820201128

下面的图为有参数的各种函数转换情况(若没有参数则直接获得当前的时间)

在这里插入图片描述

七、datetime模块

datetime 比 time 高级了不少,可以理解为 datetime 基于 time 进行了封装,提供了更多实用的函数

datetime.now()

返回当前时间

import datetime

now = datetime.datetime.now()
print(now)
# 输出结果
2020-11-28 20:15:44.940523

timedelta()

timedelta(Δ)可以方便实现日期(date实例、time实例、datetime实例)之间的运算。

import datetime

timedel = datetime.timedelta(days=2)
print(timedel)			# 时间间隔
now = datetime.datetime.now()
print(now)			# 输出当前时间
print(now + timedel)	# 输出经处理的时间
# 输出结果
2 days, 0:00:00
2020-11-28 20:09:47.057137
2020-11-30 20:09:47.057137

八、random模块

random()

返回一个0到1的小数

import random

print(random.random())
# 输出结果
0.7519760407323736

randint()

返回一个整数,包含边界

import random

print(random.randint(1, 3))

choice()

random.choice(sequence)

随机选择序列里的某个值(抓阄)

import random

list1 = ['mike', 'li', 'hua', 'ming', 'wang']
print(random.choice(list1))
# 输出结果
li

shuffle()

random.shuffle (list)

将列表里的值顺序打乱,没有返回值(洗牌)

import random

list1 = ['mike', 'li', 'hua', 'ming', 'wang']
random.shuffle(list1)
print(list1)
# 输出结果
['mike', 'wang', 'ming', 'hua', 'li']

九、hashlib模块

hashlib模块提供一些加密的算法

md5()

import hashlib

str1 = 'li,你好吗?'
md5 = hashlib.md5(str1.encode('utf-8'))	# 注意这里的编码格式
print(md5.hexdigest())			# 将加密结果以十六进制的方式输出
print(md5)
# 输出结果
3f413c7523a0bad284c6e5b84e2dc0fb
<md5 _hashlib.HASH object @ 0x000001DAA0652B50>

本文只用于个人学习与记录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值