Python进程及线程编程(2)


def write2(f):
    fs = open(f, 'a+')
    n = 10000
    while n > 0:
        fs.write('bbbbbbbbbbbbbbbb\n')
        n -= 1
    fs.close()

if __name__ == '__main__':
    f = 'test.txt'
    p1 = multiprocessing.Process(target=write1, args=(f,))
    p2 = multiprocessing.Process(target=write2, args=(f,))
    p1.start()
    p2.start()

多进程在没有加锁的情况下,没有出现写入错误的现象。

多进程加锁的写法:

#!_*_coding:utf-8_*_
#__author__:"hkey"
import multiprocessing, sys
def write1(f, lock):
    lock.acquire()
    fs = open(f, 'a+')
    n = 10000
    while n > 0:
        fs.write('aaaaaaaaaaaaaa\n')
        n -= 1
    fs.close()
    lock.release()
def write2(f, lock):
    lock.acquire()
    fs = open(f, 'a+')
    n = 10000
    while n > 0:
        fs.write('bbbbbbbbbbbbbbbb\n')
        n -= 1
    fs.close()
    lock.release()
if __name__ == '__main__':
    lock = multiprocessing.Lock()
    f = 'test.txt'
    p1 = multiprocessing.Process(target=write1, args=(f,lock))
    p2 = multiprocessing.Process(target=write2, args=(f,lock))
    p1.start()
    p2.start()

个人总结:在多进程编程中,如果只是变量的计算或者cpu计算,可以不加锁,因为每个进程的地址空间都是独立的存在。
而在写入同一个文件的时候,就有必要加锁。

4. 子进程的控制

子进程是独立与主进程的存在,创建子进程时,系统fork出子进程后,就与主进程资源完全独立了,我们不单单创建完子进程就行了,还要控制子进程
    的输入和输出。
   
    subprocess模块可以让我们非常方便的启动一个子进程,然后控制其输入和输出。

子进程输出:
使用subprocess模块,在子进程中运行 ping -n 1 baidu.com

#!_*_coding:utf-8_*_
# Author: hkey
import subprocess

print('$ ping -n 1 baidu.com')
r = subprocess.call(['ping', '-n', '1', 'baidu.com'])
print('Exit code:', r)

输出结果:

$ ping -n 1 baidu.com

正在 Ping baidu.com [111.13.101.208] 具有 32 字节的数据:
来自 111.13.101.208 的回复: 字节=32 时间=22ms TTL=51

111.13.101.208 的 Ping 统计信息:
    数据包: 已发送 = 1,已接收 = 1,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
    最短 = 22ms,最长 = 22ms,平均 = 22ms
Exit code: 0

子进程输入:

print('$nslookup')
p = subprocess.Popen(['nslookup'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, err = p.communicate(b'set q=mx\napache.org\nexit\n')    # 通过调用communicate方法实现输入,这里是二进制格式。
result = output if output else err
print(result.decode('gbk'))
print('Exit code:', p.returncode)

输出结果:
# 主机dns有问题,但是输出结果完全正确的。
$nslookup
默认服务器:  UnKnown
Address:  127.0.0.1

> > 服务器:  UnKnown
Address:  127.0.0.1

>
Exit code: 0

5. 进程间通信

虽然子进程从主进程fork后是独立的存在,但进程之间肯定是需要通信的。python的multiprocessing模块包装了底层的机制,提供了Queue、Pipes等方式
来交换数据。
进程间通信,最典型的例子就是消费者生产者模型, 生产者生产数据,消费者消费。

#!_*_coding:utf-8_*_
# Author: hkey
from multiprocessing import Process, Queue
import os, time
def write(q):
    for i in range(10):
        print('process to write: %s' % os.getpid())
        print('生产包子[%s]' %i)
        q.put(i)    # 将i上传至队列中。
        time.sleep(1)
def read(q):
    while True:
        print('process to read: %s' % os.getpid())
        values = q.get(True)    # 通过get方法将队列中的数据下载,从队列中拿走一个数据就少一个数据。
        print('吃掉包子[%s]' %values)
if __name__ == '__main__':
    q = Queue()        # 调用Queue方法生成一个队列
    pw = Process(target=write, args=(q,))    # 通过进程的方式调用
    pr = Process(target=read, args=(q,))
    pw.start()
    pr.start()
    pw.join()
    pr.terminate()    # 因为read()是死循环,需要通过terminate()方法关闭。
   
输出结果:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/065d8208ae91fda8e3f9161255ad5f63.html