python协程 读取文件_Python协程函数

1 协程函数

1.1 协程函数理解

协程函数就是使用了yield表达式形式的生成器

def eater(name):

print("%s eat food" %name)

while True:

food = yield

print("done")

g = eater("gangdan")

print(g)

结果:

generator object eater at 0x00000000028DC048

这里就证明了g现在就是生成器函数

1. 2 协程函数赋值过程

用的是yield的表达式形式

要先运行next(),让函数初始化并停在yield,相当于初始化函数,然后再send() ,send会给yield传一个值

** next()和send() 都是让函数在上次暂停的位置继续运行,

next是让函数初始化

send在触发下一次代码的执行时,会给yield赋值

**

def eater(name):

print('%s start to eat food' %name)

food_list=[]

while True:

food=yield food_list

print('%s get %s ,to start eat' %(name,food))

food_list.append(food)

e=eater('钢蛋') # wrapper('')

# print(e)

print(next(e)) # 现在是运行函数,让函数初始化

print(e.send('包子')) #

print(e.send('韭菜馅包子'))

print(e.send('大蒜包子'))

这里的关键是:

要先运行next()函数

用装饰器函数把next()函数先运行一次:

def start(func):

def wrapper(*args,**kwargs):

res=func(*args,**kwargs) # next()

next(res) # 这是关键

return res

return wrapper

@start # e = start(e)

def eater(name):

print('%s start to eat food' %name)

food_list=[]

while True:

food=yield food_list

print('%s get %s ,to start eat' %(name,food))

food_list.append(food)

e=eater('钢蛋') # wrapper('钢蛋')

print(e.send('包子'))

print(e.send('韭菜馅包子'))

print(e.send('大蒜包子'))

在@start # e = start(e) 后面写上,运行start函数,start函数返回wrapper

1.3 协程函数使用装饰器初始化

这里主要是为了防止忘记初始化next操作,在装饰器中添加

def init(func):

def wrapper(*args,**kwargs):

res = func(*args,**kwargs)

next(res) # 在这里执行next

return res

return wrapper

@init # eater=init(rater)

def eater(name):

print("%s eat food" %name)

food_list=[]

while True:

food = yield food_list

print("%s star to eat %s" %(name,food))

food_list.append(food)

print("done")

g = eater("gangdan")

# 这里就不需要next

print(g.send("1"))

print(g.send("2"))

print(g.send("3"))

print(g.send("4"))

结果:

gangdan eat food

gangdan star to eat 1

['1']

gangdan star to eat 2

['1', '2']

gangdan star to eat 3

['1', '2', '3']

gangdan star to eat 4

['1', '2', '3', '4']

只要用到装饰器函数,马上写装饰器函数,写@init马上想到** eater=init(eater) **,先执行装饰器函数。

**关键是**next(res),这里是是对生成器进行初始化。这里就会只执行一次,执行完后后面运行的都是e.send()

### 1.2 协程函数的应用 ###

过滤一个文件下的子文件、字文件夹的内容中的相应的内容,在Linux中的命令就是 *grep -rl 'python' /etc*

使用了Python的包os 里面的walk(),能够把参数中的路径下的文件夹打开并返回一个元组

```python

>>> import os

>>> os.walk('D:\test')

generator object walk at 0x0000000002ADB3B8

>>> os.walk('D:\\test') # 以后使用这种路径方式,win下

>>> os.walk(r'D:\test') # 使用r 是让字符串中的符号没有特殊意义,针对的是转义

出现错误,是因为路径的原因,但是在不同的机器上有的是可以的

>>> g=os.walk('D:\test')

>>> next(g)

Traceback (most recent call last):

File "", line 1, in

StopIteration

以后推荐是用\

>>> g=os.walk('D:\\test')

>>> next(g)

('D:\\test', ['a', 'b'], ['test.txt'])

返回的是一个元组,第一个元素是文件的路径,第二个是文件夹,第三个是该路径下的文件

1.2.1 程序流程

找文件路径 --os.walk

然后打开文件 --open

读取文件的每一行内容 -- for line in f

过滤一行内容中是否有Python if 'python' in line

打印包含Python的文件路径

程序是从上往下执行的,1产生的路径作为参数给2,2产生的给3...

上面产生的结果是下面的输入参数

1 找文件的路径

g是一个生成器,就能够用next()执行,每次next就是运行一次,这里的运行结果是依次打开文件的路径

>>> g=os.walk('D:\\test')

>>> next(g)

('D:\\test', ['a', 'b'], ['test.txt'])

>>> next(g)

('D:\\test\\a', ['a1'], ['a.txt'])

>>> next(g)

('D:\\test\\a\\a1', [], ['a1.txt'])

>>> next(g)

('D:\\test\\b', ['b1'], ['b.txt'])

>>> next(g)

('D:\\test\\b\\b1', [], ['b1.txt'])

我们在打开文件的时候需要找到文件的绝对路径,现在可以通过字符串拼接的方法把第一部分和第三部分进行拼接

用循环打开:

import os

# def serach():

g = os.walk('D:\\test')

for i in g:

print(i)

结果:

('D:\test', ['a', 'b'], ['test.txt'])

('D:\test\a', ['a1'], ['a.txt'])

('D:\test\a\a1', [], ['a1.txt'])

('D:\test\b', ['b1'], ['b.txt'])

('D:\test\b\b1', [], ['b1.txt'])

将查询出来的文件和路径进行拼接,拼接成绝对路径

import os

# def serach():

g = os.walk('D:\\test')

for i in g:

# print(i)

for j in i[-1]: # 对最后一个元素进行遍历,这些都是文件

file_path= '%s\\%s' %(i[0],j)

print(file_path)

结果:

D:\test\test.txt

D:\test\a\a.txt

D:\test\a\a1\a1.txt

D:\test\b\b.txt

D:\test\b\b1\b1.txt

这样就把文件的所有的绝对路径找出来了

用函数实现:

def search():

while True:

file_name = yield # 通过white循环能够循环接收

g = os.walk(file_name) # 这里就换成了参数

for i in g:

for j in i[-1]: # 对最后一个元素进行遍历,这些都是文件

file_path= '%s\\%s' %(i[0],j)

print(file_path)

g=search() # g就是生成器函数

next(g) # 初始化

g.send('D:\\test') # 通过send传递的是路径

2 然后打开文件

写程序中,在这里遇到的问题是 with open(file_path) as f: AttributeError: enter,不明白是为什么,然后想到open可能是系统已经用了的,所以修改名字后执行成功。

@init # 初始化生成器

def opener(target):

"打开文件,操作句柄"

while True:

file_path=yield #  接收search传递的路径

with open(file_path) as f:

target.send((file_path,f)) # send多个用元组的方式,为了把文件的路径传递下去

3 读取文件的每一行内容

@init

def cat(target):

while True:

file_path,f=yield

for line in f:

target.send((file_path,line)) # 同时传递文件路径和每一行的内容

4 过滤一行内容中是否有

@init

def grep(pattern,target): # patter是过滤的参数

while True:

file_path,line=yield

if pattern in line:

target.send(file_path) # 传递有相应内容的文件路径

5 打印包含Python的文件路径

@init

def printer():

while True:

file_path=yield

print(file_path)

上面的是函数的定义阶段,下面是函数的执行阶段:

g=search(opener(cat(grep('python',printer()))))

g.send('D:\\test')

target这个生成器:

opener(cat(grep('python',printer())))

对此的理解:

关于target还是有个点没有想明白,是target的传递的情况,我知道是从下面往上传递的。不明白的中怎么会这样接收,它的起始点在哪里

面向过程的编程思想:流水线式的编程思想,在设计程序时,需要把整个流程设计出来

优点:

1:体系结构更加清晰

2:简化程序的复杂度

缺点:

1:可扩展性极其的差,所以说面向过程的应用场景是:不需要经常变化的软件,如:linux内核,httpd,git等软件

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值