文件处理与进程和线程
1、文件读取
● open、with open可对指定路径下的文件进行处理。可指定打开模式和编码方式
● 文件打开读取文件时,可以选择单行(read)读取也可读取多行(readlines)
● 读取文件时可对读取的内容进行字符串的操作(替换、去除空白行、空格等)
● with管理上下文时,不需要判读文件是否存在,如果不存在会自动创建
def main():
path = "/Users/xiaocui/Desktop/MyLearning/致橡树.txt"
# 一次读取文件所有内容,文件较大对内存的压力较大
with open(path, mode="r", encoding="utf-8") as f:
print(f.read())
print("*" * 20)
# 每次读取一行
with open(path, mode="r", encoding="utf-8") as f:
print(f.readline())
print("-" * 20)
# 每次读取指定行数,并去掉每行首尾的空格
line_li = []
with open(path, mode="r", encoding="utf-8") as f:
for line in f.readlines():
line_new = line.strip()
line_li.append(line_new)
print(line_li)
if __name__ == "__main__":
main()
示例:
判断1 ~ 100000的素数,将1-1000的写到a.txt文件,将小于1001 - 10000的 写到b.txt,将10001 - 100000写到c.txt中
import os
import random
def write_num(num):
fileName = ["a.txt", "b.txt", "c.txt"]
filePath = "/Users/xiaocui/Desktop/MyLearning/"
num_is_prime = is_prime(num)
if 0 < num_is_prime < 100:
with open(os.path.join(filePath, fileName[0]), mode="w", encoding="utf-8") as f:
f.write(str(num_is_prime))
elif 100 < num_is_prime < 1000:
with open(os.path.join(filePath, fileName[1]), mode="w", encoding="utf-8") as f:
f.write(str(num_is_prime))
else:
with open(os.path.join(filePath, fileName[2]), mode="w", encoding="utf-8") as f:
f.write(str(num_is_prime))
def is_prime(num):
'''判断是否为素数'''
for factor in (2, num):
if num % factor == 0 and factor not in (1, num):
return False
else:
return num
for _ in range(5):
i = random.randint(1, 10000)
write_num(i)
2、进程与线程
2.1 多进程
进程:资源调度的基本单位。操作系统以进程为单位分配内存空间。每个进程会独立分配内存地址、数据栈以及进程执行过程中的缓存数据。多进程执行任务时通过进程间的通信共享数据。常用的方式有管道、共享内存区。当父进程创建子进程时,子进程会复制父进程的全部数据。
线程:线程是任务执行的基本单位。一个进程可以拥有多个线程,共享进程的内存地址。对于计算密集型的任务可使用多线程,对于I/O密集型的任务可以使用多进程。
示例一:不使用多进程
from random import randint
from time import time,sleep
def download_task(fileName):
print("开始下载%s···" % fileName)
time_to_download = randint(5, 10)
sleep(time_to_download)
print("%s下载完成!耗时%d" % (fileName, time_to_download))
def main():
start = time()
download_task("Python从入门到陌生···")
download_task("Linux基本命令···")
end = time()
print("下载文件完成!用时%d" % (end - start))
if __name__ == "__main__":
main()
>>> 运行结果
开始下载Python从入门到陌生······
Python从入门到陌生···下载完成!耗时10
开始下载Linux基本命令······
Linux基本命令···下载完成!耗时10
下载文件完成!用时20
示例二:使用多进程
Python中的多进程通过mulitprocessing模块来实现
from random import randint
from time import time,sleep
from multiprocessing import Process
from os import getpid
def down_task(fileName):
print("启动下载进程,进程号[%d]" % getpid())
print("%s开始下载" % fileName)
time_down_load = randint(5, 10)
sleep(time_down_load)
print("%s 下载完成,耗时%d秒" % (fileName, time_down_load))
def main():
start = time()
p1 = Process(target=down_task, args=("Python从入门到陌生···",))
p1.start()
p2 = Process(target=down_task, args=("Linux入门基础···",))
p2.start()
p1.join()
p2.join()
end = time()
print("总共耗时%d秒" % (end - start))
if __name__ == "__main__":
main()
>>> 运行结果
启动下载进程,进程号[10917]
Linux入门基础···开始下载
启动下载进程,进程号[10916]
Python从入门到陌生···开始下载
Python从入门到陌生··· 下载完成,耗时7秒
Linux入门基础··· 下载完成,耗时8秒
总共耗时8秒
示例二说明:
● 使用Process创建进程,target传入执行多进程的函数,args传入函数的参数,必须为元祖,代表该参数不可在外部被修改。方法start可以启动进程;join为守护进程,主进程要等待子进程执行结束才可结束。
● 对比上述两段代码的执行过程,使用多进程之后,程序的执行时间极大缩短。多进程是并行关系。
示例三:进程锁
通过加锁的方式两个函数同时对同一个文件进行写入操作
import multiprocessing
def worker_with(lock, f):
with lock:
fs = open(f, 'a+')
n = 10
while n > 1:
fs.write("Lockd acquired via with\n")
n -= 1
fs.close()
def worker_no_with(lock, f):
lock.acquire()
try:
fs = open(f, 'a+')
n = 10
while n > 1:
fs.write("Lock acquired directly\n")
n -= 1
fs.close()
finally:
lock.release()
if __name__ == "__main__":
lock = multiprocessing.Lock()
f = "file.txt"
w = multiprocessing.Process(target=worker_with, args=(lock, f))
nw = multiprocessing.Process(target=worker_no_with, args=(lock, f))
w.start()
nw.start()
w.join()
nw.join()
print("end")
说明:
● 当多个进程对共享资源同时进行访问时,会导致访问冲突,因此需要对进程加锁。使用结束之后要释放进程锁,避免资源的阻塞。
● 对于多进程的程序在使用时要保证主进程不会提前结束,否则程序执行报错。一般设置守护进程,保证主进程最后结束
2.2 多线程
Python中的多线程使用Threading模块来实现
示例一:多线程实现文件下载
from threading import Thread
from random import randint
from time import time, sleep
def down_task(fileName):
print("开始下载%s" % fileName)
time_to_down = randint(5, 10)
sleep(time_to_down)
print("%s下载完成" % fileName)
def main():
start = time()
t1 = Thread(target=down_task, args=("Python从入门到陌生",))
t1.start()
t2 = Thread(target=down_task, args=("Linux基础",))
t2.start()
t1.join()
t2.join()
end = time()
print("下载耗时为{0:.2f}秒".format(end-start))
if __name__ == "__main__":
main()
示例二:通过继承Thread类来实现多线程,需要重写run方法
from threading import Thread
from random import randint
from time import time, sleep
class Down_task(Thread):
def __init__(self, fileName):
super().__init__()
self.fileName = fileName
def run(self):
print("%s已经开始下载" % self.fileName)
time_to_down = randint(5, 10)
sleep(time_to_down)
print("%s已经下载完成,耗时%d秒" % (self.fileName, time_to_down))
def main():
start = time()
t1 = Down_task("Python从入门到陌生")
t1.start()
t2 = Down_task("Linux基础")
t2.start()
t1.join()
t2.join()
end = time()
print("总共耗时{0:.2f}秒".format(end - start))
if __name__ == "__main__":
main()
2.3 多线程之间的通信
一个进程中的多个线程共享进程的内存资源。因此会出现多个线程共同“竞争”同一块内存资源的情况。会导致内存中的变量混乱,因此对临界资源进行操作时需要加上保护机制。一般要加锁对共享资源进行维护。
示例一:
使用锁对线程访问资源进行控制。锁的机制保证在一个线程对共享资源进行操作时,其他线程不能访问该资源。
错误示范:
from time import sleep
from threading import Thread
class Account:
def __init__(self):
self._balance = 0
def deposit(self, money):
'''计算余额'''
new_balance = self._balance + money
sleep(0.01)
# 更新账户
self._balance = new_balance
@property # balance变成了属性
def balance(self):
return self._balance
class Addaccount(Thread):
def __init__(self, account, money):
super().__init__()
self._account = account
self._money = money
def run(self):
self._account.deposit(self._money)
def main():
account = Account()
threads = []
for _ in range(10):
t = Addaccount(account, 10)
threads.append(t)
t.start()
# 设置守护线程
for t in threads:
t.join()
print("账户当前可用余额为%s元" % account.balance)
if __name__ == "__main__":
main()
加锁:在每个线程给账户增加金额时保证一个时间段只有一个线程可以操作。其余线程都要等待。
from time import sleep
from threading import Thread,Lock
class Account:
def __init__(self):
# balance、lock是定义的共享变量
self._balance = 0
self._lock = Lock()
def deposit(self, money):
'''计算余额'''
# 加锁
self._lock.acquire()
try:
new_balance = self._balance + money
sleep(0.01)
# 更新账户
self._balance = new_balance
finally:
# 执行完之后要释放锁,便于其他线程调用
self._lock.release()
@property
def balance(self):
return self._balance
class Addaccount(Thread):
def __init__(self, account, money):
super().__init__()
self._account = account
self._money = money
def run(self):
self._account.deposit(self._money)
def main():
account = Account()
threads = []
for _ in range(10):
t = Addaccount(account, 10)
threads.append(t)
t.start()
# 设置守护线程
for t in threads:
t.join()
print("账户当前可用余额为%s元" % account.balance)
if __name__ == "__main__":
main()