Python进程和线程操作

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tianmaxingkong_/article/details/54766764

一.进程

1.进程的运行环境

    每个运行的进程,系统都会分配一个相关的运行环境,一般的可以将该运行环境认为是进程环境变量的集合,当进程启动的时候,环境变量就确定了,只有当前进程才能够修改其环境变量。Python的os模块中提供了environ属性,来记录当前进程的运行环境,environ是字典数据结构,以key-value的方式存储环境变量(key是环境变量的变量名,一般要求字母全部大写),value是对应的环境变量的值:

import os

path = os.environ.get('PATH')
print path
获得进程所有的环境变量:

import os

for key in os.environ.keys():
    print key, os.environ[key]


2.创建进程

2.1使用os模块创建进程

    os模块中用来创建进程的函数有system和exec家族函数,使用system创建进程:

import os

os.system('ls')
上面的程序在当前进程中开启了一个新的进程,在相当于在命令行中执行ls操作(Mac和Linux中的ls,Windows中的dir命令)。


在开发中,有时需要运行其他的进程来处理一些事务,e.g.在Windows上运行一个exe文件转换图片的sRGB格式:

import os

# magick.exewindows7上转换图片sRGB格式的工具
commandTool = os.getcwdu()+os.sep+'magick.exe'

# 处理tmp文件夹中的图片
def convertsRGBImageFromTmp(pngPath):
    command = "{0} {1} {2}".format(commandTool, pngPath, pngPath)
    statCode = os.system(command)
【说明】

在cocos2d/wxPython开发过程中,由于win7对图片格式审核升级的原因,有时会有sRGB警告的弹窗,此时可以使用magick.exe工具进行格式转换,上面的代码使用了os.system(command)开启新进程来处理。


exec家族函数同样可以开启新进程,下面使用execl开启新的进程运行textExec.py文件中的代码:

import os

os.execl("testExec.py", '1', '2')


testExec.py文件:

#coding=utf-8

import os,sys

print "current pid: ", os.getpid()

print sys.argv

len = len(sys.argv)
for i in range(len):
    print sys.argv[i]
【说明】

os.execl函数运行了testExec.py文件,并传递了两个参数,分别为,1,2。执行之后的结果:



同样的,使用os.system也可以实现上面的效果:

import os

statCode = os.system("python testExec.py 1 2 3")

【说明】

os.system执行成功之后返回0,os.exec家族没有返回值,执行失败会触发OSError。

os.system是调用系统内置命令来执行操作,命令操作结束之后会将控制权返回到启动进程,os.exec家族函数在执行命令之后会接管启动进程,而不是返回控制权,这样启动新进程的进程在执行os.exec家族函数之后便终止。


2.2使用subprocess管理进程

import subprocess
import os

print os.getpid()

pingP = subprocess.Popen("ping www.baidu.com", shell=True)
print pingP.pid
print pingP.returncode

运行效果:



3. 进程终止

os和sys模块分别提供了os.abort和sys.exit方法来终止进程,sys.exit()方法较为温和,在退出之前会执行一些清理操作,同时将执行的返回值返回,如果返回0表示进程退出成功,os.abort函数回直接向进程发送终止信号,一般情况下进程会立即终止,并不会进行相关的清理操作。


二.线程

Python中对线程的支持有两种方式:

 | 低级线程模块 thread

 | 高级线程模块 threading


threading模块是基于thread的,Python中提供了Queue模块实现多线程数据同步,Queue使用了FIFO(first in first out)队列模型。

1.线程创建

使用thread模块创建多线程:

import thread
import time

def worker(index, create_time):
    print index, ' thread'

for i in range(5):
    time.sleep(1)
    # start_new_thread函数的第二个参数是一个元组
    thread.start_new_thread(worker, (i, time.time()))
【说明】

thread中还有其他的方法:

 start_new_thread  生成一个新的线程,并返回其标示符

   exit  退出当前线程,触发SystemError

   get_ident  获取当前线程的标示符

 stack_size  获取线程堆栈的大小


使用高级模块threading创建新的线程:

# coding=utf-8

import threading
import time

class ThreadE(threading.Thread):
    def __init__(self, index, time_create):
        threading.Thread.__init__(self)

        self.time_create = time_create
        self.index = index
    def run(self):
        time.sleep(1)
        print 'Thread Index:', self.index
        print 'Thread Name:', self.getName()
        pass

for i in range(5):
    thread = ThreadE(i, time.time())
    thread.start()
自定义一个类,需要继承自threading.Thread,需要实现run()方法,在run()方法中进行线程操作。


2.线程的私有变量

    Java多线程中,每一个线程有一个ThreadLocal容器用来存储线程的私有变量,在Python中同样提供了类似的容器:

import threading
import time

class ThreadE():
    def __init__(self, index):
        self.local = threading.local()
        self.index = index
    def run(self):
        self.local.index = self.index
        time.sleep(1)
        print 'Thread Index:', self.local.index, self.index
        pass

e = ThreadE(2)
t = threading.Thread(target=e.run)
t.start()
【说明】

上面的代码除了演示threadinf.local的用法之外,还可以看出threading创建多线程的另外一种方法,和Java创建多线程中的Thread和Runnable相似。


3.Python线程的锁机制

Python多线程的低级模块和高级模块中分别提供了线程锁的机制:

 | 低级模块thread -> thread.allocate_lock()

 | 高级模块threading -> threading.Lock()

在thread中:

# coding=utf-8

import thread, time
import threading

class Counter():
    def __init__(self):
        self.value = 0
        self.lock = thread.allocate_lock()
        pass
    def increment(self):
        self.lock.acquire()
        self.value = self.value +1
        self.lock.release()
        v = self.value
        return v

couter = Counter()
class ThreadExample(threading.Thread):
    def __init__(self, index):
        threading.Thread.__init__(self)

        self.index = index
        pass
    def run(self):
        time.sleep(1)
        c = "{0} --- {1}".format(self.index, couter.increment())
        print c


for i in range(10):
    t = ThreadExample(i)
    t.start()

在threading中:

class Counter():
    def __init__(self):
        self.value = 0
        self.lock = threading.Lock()
        pass
    def increment(self):
        self.lock.acquire()
        self.value = self.value +1
        self.lock.release()
        v = self.value
        return v

运行的效果:

0 --- 1
1 --- 2
3 --- 3
2 --- 4
4 --- 5
7 --- 6
5 --- 7
6 --- 8
8 --- 9
9 --- 10
【说明】

上面运行的效果可以看到,虽然线程的index并不是按照顺序运行的,但是Counter的增长却是按照顺序增长的,可见两种锁机制都可以实现数据同步的功能。


4.Python的同步队列

    Python提供了Queue模块,该模块中提供了一个FIFO的队列,可以实现数据的同步:

#coding=utf-8

import threading
import Queue, time

class WorkThread(threading.Thread):
    def __init__(self, index, queue):
        threading.Thread.__init__(self)

        self.index = index
        self.queue = queue
        pass
    def run(self):
        while True:
            time.sleep(1)
            item = self.queue.get()

            if item is None:
                break
                # 此处若为continue,线程将一直运行在后台
                # continue

            c = "{0} --- {1}".format(self.index, item)
            print c

queue = Queue.Queue(0)
for index in range(5):
    WorkThread(index, queue).start()


for i in range(10):
    queue.put(i)

运行的结果:

0 --- 0
1 --- 1
2 --- 2
3 --- 4
4 --- 3
0 --- 5
1 --- 6
2 --- 7
4 --- 8
3 --- 9
【说明】

Queue模块中的Queue构造函数可以实例化一个FIFO的同步队列,Queue的构造函数中有一个maxsize的参数,当maxsize=0表示队列长度无限制,Queue实例使用put(task)将任务task存储到同步队列中,使用get()方法获取并移除同步队列中的任务。


猜你喜欢

转载自blog.csdn.net/tianmaxingkong_/article/details/54766764