怎么将django的php 单线程 多线程启动改为多线程启动

Django中异步任务Celery - 推酷
Django中异步任务Celery
本文主要讲述怎么在Django中应用Celery来完成异步任务.
最近公司在做支付宝接入的任务。主要是我们的系统和支付宝进行对接。也就是封装点API接口。在其中遇到一个问题,是这样的。支付宝的回调地址分为前台
后台异步回调
,我们的系统必须在接到支付宝异步回调之后做些事情,但这些事情比较耗时,大概会花费2~3秒的样子,这对API接口的响应是无法接受的。后来想到了利用多线程来处理。但是Django貌似不支持多线程。即便是在一起请求过来后开启多线程去执行任务。照样会阻塞请求线程。最后经过Google 查到了
的存在。下面来介绍下怎么应用在Django项目中。
一、什么是 Celery
官网描述如下:Celery是一个基于消息传递的异步任务队列。关注与时时操作,但是也支持任务调度。执行单元称之为Task,被一个或多个worker处理。该woker是使用multiprocessing,
。Task能够被异步(后台)执行也可以被同步(等待完成)执行。Celery在生产服务器每天处理数以万计的Task。访问
查看更多信息。
可见Celery主要是用来处理
的。但我们为什么需要异步任务。或者定时任务呢?
1.1 假设用户发起一个
返回。但是在request 经过django一层层处理到达我们的view时,view要进行一次比较耗时的操作,比如分析日志文件或者发起一个http请求。这些操作耗时无法确定,这样我们的API接口的响应时间就无法预知了。为了给用户以良好的体验,我们应该把这种耗时的任务放在后台处理。
1.2 定时任务,之前遇到一个需求是这样的。根据Django的日志数据分析用户的访问习惯和页面访问次数。这种任务不可能在用的时候再去分析统计,那肯定来不及了。所以需要在每天零点整自动分析这些日志。当遇到这种问题时我们可以采用
的定时任务。当然还有另一种解决方案,自定义
Django Command
然后用shell脚本执行。然后添加到系统定时任(crontab)务里。
二、本文所依赖的库
django-celery
三、依赖库的安装
这里推荐vietualenv+virtualenvwarpper管理依赖环境,真心很方便
pip install django
pip install celery
pip install&django-celery
四、开始编码
django-admin.
startproject celery_tutorial
celery_tutorial/
django-admin.
startapp main
五、django设置
我们暂时使用django runserver来启动celery. 而Celery代理人(broker), 我们使用Django database broker implementation. 现在我们只需要知道Celery需要broker, 使用django自身便可以充当broker. (但在部署时, 我们最好使用更稳定和高效的broker, 例如Redis.)
在settings.py中:
setup_loader
BROKER_URL
'django://'
INSTALLED_APPS
'djcelery'
'kombu.transport.django'
第一二项是必须的, 第三项则告诉Celery使用Django项目作为broker.
在INSTALLED_APPS中添加的djcelery是必须的. kombu.transport.django则是基于Django的broker
最后创建Celery所需的数据表, 运行:
python manage.
六、配置View 以及 URL
新建并配置
celery_tutorial/celery_tutorial/tasks.py
# encoding:utf-8
_do_kground_work
这里用time 模拟耗时操作
'hello:%s %s'
celery_tutorial/celery_tutorial/views.py
# encoding:utf-8
HttpResponse
_do_kground_work
_do_kground_work.
'GreenPine'
HttpResponse
'Hello, World!'
celery_tutorial/celery_tutorial/urls.py
urlpatterns
运行项目:
a、启动woker
正如之前说到的, 我们需要worker来执行task. 以下是在开发环境中的如何启动worker:
首先启动terminal, 如同开发django项目一样, 激活virtualenv, 切换到django项目目录. 然后启动django自带web服务器: python manage.py runserver.
python manage.
celery worker --loglevel
再生产环境中可以用如下命令启动woker,并用supervisor监控:
nohup python manage.
celery worker —loglevel
b、测试task
在浏览器里输入
http://localhost:8000/
此时请求会非常迅速,瞬间就返回了而不是等待
_do_kground_work
如果你观察woker终端 你会发现有这样的输出:
[ 16:13:25,490: INFO/MainProcess] Received task: main.tasks._do_kground_work[001a4d4b-4d9e-4a70-b2b4-876aca30a010]
[ 16:13:25,493: WARNING/Worker-1] hello:GreenPine 1
[ 16:13:26,494: WARNING/Worker-1] hello:GreenPine 2
[ 16:13:27,496: WARNING/Worker-1] hello:GreenPine 3
[ 16:13:28,498: WARNING/Worker-1] hello:GreenPine 4
[ 16:13:29,499: WARNING/Worker-1] hello:GreenPine 5
[ 16:13:30,499: WARNING/Worker-1] hello:GreenPine 6
[ 16:13:31,501: WARNING/Worker-1] hello:GreenPine 7
[ 16:13:32,502: WARNING/Worker-1] hello:GreenPine 8
[ 16:13:33,503: WARNING/Worker-1] hello:GreenPine 9
[ 16:13:34,527: INFO/MainProcess] Task main.tasks._do_kground_work[001a4d4b-4d9e-4a70-b2b4-876aca30a010] succeeded in 9.s: None
参考文章:
写作时长:4个小时,如有错误之处欢迎拍砖指正
本文属于quxl原创,未经允许禁止转载。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致> 博客详情
摘要: 继续学习python基础,多线程编程
&&&&python多线程编程,一般使用thread和threading模块。thread模块想对较底层,threading模块对thread模块进行了封装,更便于使用。所有,通常多线程编程使用threading模块。
(一)threading模块
Thread&线程类,这是我们用的最多的一个类,你可以指定线程函数执行或者继承自它都可以实现子线程功能;
Timer与Thread类似,但要等待一段时间后才开始运行;
Lock&锁原语,这个我们可以对全局变量互斥时使用;
RLock&可重入锁,使单线程可以再次获得已经获得的锁;
Condition&条件变量,能让一个线程停下来,等待其他线程满足某个“条件”;
Event&通用的条件变量。多个线程可以等待某个事件发生,在事件发生后,所有的线程都被激活;
Semaphore为等待锁的线程提供一个类似“等候室”的结构;
BoundedSemaphore&与semaphore类似,但不允许超过初始值;
Queue:实现了多生产者(Producer)、多消费者(Consumer)的队列,支持锁原语,能够在多个线程之间提供很好的同步支持。
&&&&(1)threading.Thread类
getName(self)&返回线程的名字
isAlive(self)&布尔标志,表示这个线程是否还在运行中
isDaemon(self)&返回线程的daemon标志
join(self,&timeout=None)&程序挂起,直到线程结束,如果给出timeout,则最多阻塞timeout秒
run(self)&定义线程的功能函数
setDaemon(self,&daemonic)&把线程的daemon标志设为daemonic
setName(self,&name)&设置线程的名字
start(self)&开始线程执行
&&&&(2)threading.Queue类
LifoQueue后入先出(LIFO)队列
PriorityQueue&优先队列
(二)线程的创建
&&&&线程的创建一般有两种:①将创建的函数传递进threading.Thread()对象。②继承threading.Thread类,通常重写run()方法。
&&&&(1)使用threading.Thread(),实例化一个线程
#&-*-&coding:&utf-8&-*-
import&threading
#&使用threading.Thread(),实例化一个线程
&&&&print&threading.current_thread().getName()
#&创建线程对象
t1&=&threading.Thread(target=T,&name='tt11')
#&启动线程
t1.start()
&&&&(2)创建threading.Thread 的子类, 并覆盖run() 方法
#&-*-&coding:&utf-8&-*-
import&threading
#&创建threading.Thread&的子类,&并覆盖run()&方法
class&T(threading.Thread):
&&&&#&重写父类run()方法
&&&&def&run(self):
&&&&&&&&print&self.getName()
#&实例化线程,并运行
t1.start()
&&&&(3)例子
#&-*-&coding:&utf-8&-*-
import&threading
class&T(threading.Thread):
&&&&def&__init__(self):
&&&&&&&&threading.Thread.__init__(self)
&&&&def&run(self):
&&&&&&&&pass
def&main():
&&&&t&=&T()
&&&&t.start()
if&__name__&==&'__main__':
&&&&main()
&&&&(4)join方法
&&&&&&&&用来阻塞上下文,直到该线程结束。
def&join(self,&timeout=None):
&&&&(5)setDaemon方法
守护线程&&&&
当我们在程序运行中,执行一个主线程,如果主线程又创建一个子线程,主线程和子线程就分兵两路,
当主线程完成想退出时,会检验子线程是否完成。如果子线程未完成,则主线程会等待子线程完成后再退出。
但是有时候我们需要的是,只要主线程完成了,不管子线程是否完成,都要和主线程一起退出,
这时就可以用setDaemon方法,并设置其参数为True。
(三)共享资源的访问
&&&&共享资源,互斥与同步。
&&&&(1)简单的threading.Lock() 锁
#&-*-&coding:&utf-8&-*-
import&threading
counter&=&0
mutex&=&threading.Lock()
class&T(threading.Thread):
&&&&def&__init__(self):
&&&&&&&&threading.Thread.__init__(self)
&&&&def&run(self):
&&&&&&&&#&全局变量
&&&&&&&&global&counter,&mutex
&&&&&&&&time.sleep(1)
&&&&&&&&#&获得加锁
&&&&&&&&if&mutex.acquire():
&&&&&&&&&&&&counter&+=&1
&&&&&&&&&&&&#&释放锁
&&&&&&&&&&&&mutex.release()
def&main():
&&&&t&=&T()
&&&&t.start()
if&__name__&==&'__main__':
&&&&main()
当一个线程调用Lock对象的acquire()方法获得锁时,这把锁就进入“locked”状态。
因为每次只有一个线程1可以获得锁,所以如果此时另一个线程2试图获得这个锁,该线程2就会变为“blo同步阻塞状态。
直到拥有锁的线程1调用锁的release()方法释放锁之后,该锁进入
“unlocked”状态。线程调度程序从处于同步阻塞状态的线程中选择一个来获得锁,并使得该线程进入运行(running)状态。
&&&&(2)可重入锁 threading.RLock()&
&&&&&&&&当线程在获得加锁之后,又需要共享资源,需要再次加锁。但...
#&-*-&coding:&utf-8&-*-
import&threading
counter&=&0
mutex&=&threading.Lock()
#&mutex&=&threading.RLock()
class&T(threading.Thread):
&&&&def&__init__(self):
&&&&&&&&threading.Thread.__init__(self)
&&&&def&run(self):
&&&&&&&&#&全局变量
&&&&&&&&global&counter,&mutex
&&&&&&&&time.sleep(1)
&&&&&&&&#&获得加锁
&&&&&&&&if&mutex.acquire():
&&&&&&&&&&&&counter&+=&1
&&&&&&&&&&&&#&再次加锁
&&&&&&&&&&&&if&mutex.acquire():
&&&&&&&&&&&&&&&&counter&+=&1
&&&&&&&&&&&&&&&&mutex.release()
&&&&&&&&&&&&#&释放锁
&&&&&&&&&&&&mutex.release()
def&main():
&&&&t&=&T()
&&&&t.start()
if&__name__&==&'__main__':
&&&&main()
此时程序会挂起,也就是形成了最简单死锁。
在Python中为了支持在同一线程中多次请求同一资源,引入了‘可重入锁’。
count&记录了acquire的次数,从而使得资源可以被多次require。
直到一个线程所有的acquire都被release,其他的线程才能获得资源。
def&RLock(*args,&**kwargs):
&&&&return&_RLock(*args,&**kwargs)
class&_RLock(_Verbose):
&&&&def&__init__(self,&verbose=None):
&&&&&&&&_Verbose.__init__(self,&verbose)
&&&&&&&&self.__block&=&_allocate_lock()
&&&&&&&&self.__owner&=&None
&&&&&&&&self.__count&=&0
&&&&(3)使用Condition实现复杂的同步
Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还提供了wait和notify方法。
使用Condition的主要方式为:
线程首先acquire一个条件变量,然后判断一些条件。
如果条件不满足则wait;
如果条件满足,进行一些处理改变条件后,通过notify方法通知其他线程,其他处于wait状态的线程接到通知后会重新判断条件。
不断的重复这一过程,从而解决复杂的同步问题。
&&&&&&&&一个经典的例子。生产者消费者问题。(理解上述,代码其实很简单。)
import&threading&&
import&time&&
condition&=&threading.Condition()&&
products&=&0&&
class&Producer(threading.Thread):&&
&&&&def&__init__(self):&&
&&&&&&&&threading.Thread.__init__(self)&&
&&&&&&&&&&
&&&&def&run(self):&&
&&&&&&&&global&condition,&products&&
&&&&&&&&while&True:&&
&&&&&&&&&&&&if&condition.acquire():&&
&&&&&&&&&&&&&&&&if&products&&&10:&&
&&&&&&&&&&&&&&&&&&&&products&+=&1;&&
&&&&&&&&&&&&&&&&&&&&print&"Producer(%s):deliver&one,&now&products:%s"&%(self.name,&products)&&
&&&&&&&&&&&&&&&&&&&&condition.notify()&&
&&&&&&&&&&&&&&&&else:&&
&&&&&&&&&&&&&&&&&&&&print&"Producer(%s):already&10,&stop&deliver,&now&products:%s"&%(self.name,&products)&&
&&&&&&&&&&&&&&&&&&&&condition.wait();&&
&&&&&&&&&&&&&&&&condition.release()&&
&&&&&&&&&&&&&&&&time.sleep(2)&&
&&&&&&&&&&
class&Consumer(threading.Thread):&&
&&&&def&__init__(self):&&
&&&&&&&&threading.Thread.__init__(self)&&
&&&&&&&&&&
&&&&def&run(self):&&
&&&&&&&&global&condition,&products&&
&&&&&&&&while&True:&&
&&&&&&&&&&&&if&condition.acquire():&&
&&&&&&&&&&&&&&&&if&products&&&1:&&
&&&&&&&&&&&&&&&&&&&&products&-=&1&&
&&&&&&&&&&&&&&&&&&&&print&"Consumer(%s):consume&one,&now&products:%s"&%(self.name,&products)&&
&&&&&&&&&&&&&&&&&&&&condition.notify()&&
&&&&&&&&&&&&&&&&else:&&
&&&&&&&&&&&&&&&&&&&&print&"Consumer(%s):only&1,&stop&consume,&products:%s"&%(self.name,&products)&&
&&&&&&&&&&&&&&&&&&&&condition.wait();&&
&&&&&&&&&&&&&&&&condition.release()&&
&&&&&&&&&&&&&&&&time.sleep(2)&&
&&&&&&&&&&&&&&&&&&
if&__name__&==&"__main__":&&
&&&&for&p&in&range(0,&2):&&
&&&&&&&&p&=&Producer()&&
&&&&&&&&p.start()&&
&&&&&&&&&&
&&&&for&c&in&range(0,&10):&&
&&&&&&&&c&=&Consumer()&&
&&&&&&&&c.start()
&&&&(4)使用 threading.Event 实现线程间通信
使用threading.Event可以使一个线程等待其他线程的通知,我们把这个Event传递到线程对象中,
Event默认内置了一个标志,初始值为False。
一旦该线程通过wait()方法进入等待状态,直到另一个线程调用该Event的set()方法将内置标志设置为True时,
该Event会通知所有等待状态的线程恢复运行。
import&threading&&
import&time&&
class&MyThread(threading.Thread):&&
&&&&def&__init__(self,&signal):&&
&&&&&&&&threading.Thread.__init__(self)&
&&&&&&&&#&初始化&
&&&&&&&&self.singal&=&signal&&
&&&&&&&&&&
&&&&def&run(self):&&
&&&&&&&&print&"I&am&%s,I&will&sleep&..."%self.name&&
&&&&&&&&#&进入等待状态
&&&&&&&&self.singal.wait()&&
&&&&&&&&print&"I&am&%s,&I&awake..."&%self.name&&
&&&&&&&&&&
if&__name__&==&"__main__":
&&&&#&初始&为&False&
&&&&singal&=&threading.Event()&&
&&&&for&t&in&range(0,&3):&&
&&&&&&&&thread&=&MyThread(singal)&&
&&&&&&&&thread.start()&&
&&&&print&"main&thread&sleep&3&seconds...&"&&
&&&&time.sleep(3)&&
&&&&# 唤醒含有signal, 处于等待状态的线程&&
&&&&singal.set()
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&-- 日03:53:22
人打赏支持
码字总数 69939
支付宝支付
微信扫码支付
打赏金额: ¥
已支付成功
打赏金额: ¥
& 开源中国(OSChina.NET) |
开源中国社区(OSChina.net)是工信部
指定的官方社区单线程和多线程的简单理解 - 简书
单线程和多线程的简单理解
线程:简单的说就是处理事务的任务链,当只有一条链,所有的事情都在这一条链上执行时,那就是单线程,单线程有很多缺点,就是当执行某个耗时或者不能立即完成的任务时,比如:网络通讯、复杂运动,该线程就会暂时停止对其他任务的响应和处理,造成的视觉效果就是程序的“假死”,也就是应用程序被卡在那里无法继续执行,因此在多数情况下,单线程的应用很少。而当有多条链时,那就是多线程了,当然并不是说多条线并行,而是说有一条主线程,处理整个程序任务的主方向的链,而其链上又有许许多多的分支,就像树枝那样,这样,既有了主线程去处理那些主要任务,又有了那些细小线程去处理耗时费力任务,从而让界面看起来更加流畅。iOS平台对多线程的支持iOS平台提供了非常优秀的多线程支持,程序可以通过非常简单的方式来启动多线程,iOS平台不仅提供了NSThread类来创建多线程,还提供了GCD方式来简化多线程编程,提供了NSOperation和NSOperationQueue支持多线程编程。线程和进程几乎所有的操作系统都支持同时运行多个任务,一个任务通常就是一个程序,每个运行中的程序就是一个进程。
当一个程序运行时,内部可能包含了多个顺序执行流,每个顺序执行流就是一个线程。几乎所有的操作系统都支持进程的概念,所有运行中的任务通常对应一个进程(Process)。当一个程序进入内存,运行后,即变成一个进程。进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位。一般而言,进程包含如下3个特征:
独立性:进程是系统中独立存在的实体,它可以拥有自己独立的资源,每一个进程都拥有自己私有的地址空间。在没有经过进程本身允许的情况下,一个用户进程不可以直接就访问其他进程的地址空间。
动态性:进程与程序的区别在于,程序只是一个静态的指令集合,而进程是一个正在系统中活动的指令集合。在进程中加入了时间的概念。进程具有自己的生命周期和各种不同的状态,这些概念在程序中都是不具备的。
并发性:多个进程可以在单个处理器上并发执行,多个进程之间不会互相影响。并发性(concurrency)和并行性(parallel)是两个不同的概念。并行指在同一时刻,有多条指令在多个处理器上同时执行;并发指在同一时刻,只能有一条指令执行,但多个进程指令被快速轮换执行(纳秒级),使得在宏观上具有多个进程同时执行的效果。
大部分操作系统都支持多进程并发运行,现代的操作系统几乎都支持同时运行多个任务对于一个CPU而言,它在某个时间点上只能执行一个程序,也就是说,只能运行一个进程,CPU不断地在这些进程之间轮换执行。为什么感觉不到任何中断现象?这是因为CPU的执行速度相对人类的感觉而言是在是太快了。当然,如果启动的程序足够多,依然可以感觉到程序的运行速度下降。所以虽然CPU在多个进程之间轮换执行,但感觉到(宏观上)好像多个进程在同时执行。现代的操作系统都支持多进程的并发(轮换执行),但在具体的实现细节上可能因为硬件和操作系统的不同而采用不同的策略。目前操作系统大多采用效率更高的抢占式多任务策略,例如WindowsNT、windows2000以及UNIX/Linux等操作系统。多线程则扩展了多进程的概念,使得同一个进程可以同时并发(轮换执行)处理多个任务。线程(Thread)也被称作轻量级进程(LightweightProcess),线程是进程的执行单元。就像进程在操作系统中的地位一样,线程在进程中是独立的、并发的执行流。进程操作系统--线程进程当进出被初始化后,主线程就被创建了对于应用程序而言,通常至少有一个主线程,可以在该进程内创建多条顺序执行流,这些顺序执行流就是线程,每条线程也是相互独立的;线程是进程的的组成部分,一个进程可以拥有多个线程,一个线程必须有一个父进程,线程可以拥有自己的堆栈、自己的程序计数器和自己的局部变量,但是不再拥有系统资源,它与父进程的其他线程共享该进程所拥有的全部资源。因为多个线程共享父进程里的全部资源,因此编程更加方便;但必须更加小心,必须确保线程不会妨碍同一进程里的其他线程。
线程可以完成一定的任务,可与其他线程共享父进程中的共享变量及部分环境,相互之间协同来完成进程所要完成的任务;
线程是独立运行的,它并不知道进程中是否还有其他线程存在。线程的执行是抢占式的,也就是说,当前运行的线程在任何时候都可能被挂起,以便另一个线程可以运行;
一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行;
从逻辑角度看,多线程存在于一个运行中的应用程序中,让一个运行中的应用程序中可以有多个执行部分同时执行(宏观上),但操作系统无须将多个线程看作多个独立的应用,对多线程实现调度和管理以及资源分配。线程的调度和管理由进程本身负责完成。简而言之,一个程序运行后至少有一个进程,一个进程里至少要包含一个线程(即主线程),可以包含多个线程。操作系统可以同时执行多个任务,每个任务就是进程;进程可以同时执行多个任务,每个任务就是线程。多线程线程在运行中的程序中是独立的、并发的执行流,与分隔的进程相比,进程中的线程之间的隔离程序要小,因为它们共享内存、文件句柄和其它每个进程应有的状态。
因为线程的划分尺度小于进程,使得多线程程序的并发性高。进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。线程比进程具有更高的性能:这是因为同一个进程中的线程都有共性——多个线程将共享同一个进程虚拟空间。线程共享的环境包括:进程代码段、进程的公有数据等。利用这些共享的数据等,线程很容易实现相互之间的通信。当操作系统创建一个进程时,必须为该进程分配独立的内存空间,并分配大量的相关资源;但创建一个线程则简单很多,因此使用多线程来实现并发比使用多进程实现并发的性能要高得多。使用多线程编程具有如下优点:
进程之间不能共享内存,但同一进程中的线程之间共享内存非常容易;
系统创建进程需要为该进程重新分配系统资源,但创建线程则代价小得多,因此使用多线程来实现多任务并发比多进程的效率高;下次自动登录
现在的位置:
& 综合 & 正文
从django 启动守护进程
希望通过django启动一个在后台一直运行的.
无论是通过使用多线程(threading),还是多进程(subprocess, multiprocessing, os.fork),页面都会返回内容,但一直处于继续等待的界面.分析原因是在django中启动线程后除非kill掉启动的线程或者线程自己结束,否则django都会认为还有消息要返回.
于是考虑建立一个daemon,在django启动后与其交互.但如此daemon和django要分开启动比较麻烦.决定让daemon在django启动的过程中启动.方法是将建立daemon人过程放在django 的settings.py中.
很意外,django在启动过程中居然加载了5次settings.py文件,我的daemon也启动了5次.而且一开始我的daemon只是简单的通过pipe进行交互:
p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
in, out = p.stdin, p.stdout
之后的控制必须要
from settings import in, out
in.writes(cmd + "/n")
in.flush()
如上,有三个问题.
1.通过pipe进行命令交互时,若是A启动B,然后A与B进行交互是没问题的,但因为我的程序要封装一层,结果会成为A启动B, B启动C,A与B间通过简单的调用进行交互,B与C间通过PIPE通信,然后A指导B对C发送命令,不知道什么原因,PIPE通信居然不可行了.
2.PIPE通信有个弊端,只能在local端通信,但根据需求之后会有多个服务器的,所以PIPE通信其实不可行.
3.如何防止启动django时启动多个daemon
1.将PIPE通信直接改成socket通信,以后的命令直接通过socket交互,这样以上的问题1与2都解决了
s = socket.socket(socket.AF_INET,
socket.SOCK_DGRAM)
s.bind(("", port))
while True:
data, addr = s.recvfrom(1024)
print("do something")
2.防止启动多个deamon的方法也很简单,修改上述,通过查看端口是否被占用决定是否继续运行.
s = socket.socket(socket.AF_INET,
socket.SOCK_DGRAM)
s.bind(("", port))
#当端口被使用时直接退出,不再启动
sys.exit(0)
while True:
data, addr = s.recvfrom(1024)
如果只是简单的新建一个线程daemon或进程daemon,当django退出时,这些伪daemon也会消失.在linux下,想要成为真正的daemon必须如下(参考python cookbook),这样保证django出现意外时客户端依然能保持与守护进程的通信:
pid = os.fork()
if pid & 0:#退出父进程,进入子进程
sys.exit(0)
#建立session id,脱离当前终端控制
os.chdir('/')
os.umask(0)
os.setsid()
#成为真正的daemon
pid = os.fork()
if pid & 0:#退出父进程,进入子进程,这时真正成为daemon,
sys.exit(0)
s = socket.socket(socket.AF_INT, socket.SOCK_DGRAM)
s.bind(("", port))
sys.exit(0)
while True:
data, addr = s.recvfrom(1024)
&&&&推荐文章:
【上篇】【下篇】}

我要回帖

更多关于 多线程与单线程的区别 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信