需要帮助了解 python 线程风格
Need help understanding python threading flavors
我现在很喜欢线程并探索线程和线程库。当我开始使用它们时,我编写了 2 个基本程序。以下是 2 个程序及其相应的输出:
threading_1.py :
import threading
def main():
t1=threading.Thread(target=prints,args=(3,))
t2=threading.Thread(target=prints,args=(5,))
t1.start()
t2.start()
t1.join()
t2.join()
def prints(i):
while(i>0):
print "i="+str(i)+"\n"
i=i-1
if __name__=='__main__':
main()
输出:
i=3
i=2
i=5
i=4
i=1
i=3
i=2
i=1
thread_1.py
import thread
import threading
def main():
t1=thread.start_new_thread(prints,(3,))
t2=thread.start_new_thread(prints,(5,))
t1.start()
t2.start()
t1.join()
t2.join()
def prints(i):
while(i>0):
print "i="+str(i)+"\n"
i=i-1
if __name__=='__main__':
main()
输出:
Traceback (most recent call last):
i=3
File "thread_1.py", line 19, in <module>
i=2
i=1
main()
i=5
i=4
i=3
i=2
i=1
File "thread_1.py", line 8, in main
t1.start()
AttributeError: 'int' object has no attribute 'start'
我想要的输出与 threading_1.py 中的一样,其中交错打印使它成为一个令人信服的线程执行示例。我的理解是 "threading" 与 [=38= 相比 higher-class library ]。而我进入 thread_1.py 的 AttributeError 是因为我在从线程库启动的线程上运行而不是线程。
所以,现在我的问题是 - 如何使用 thread_1.py 实现类似于 threading_1.py 的输出。是否可以修改或调整程序以产生相同的结果?
简短回答:忽略 thread
module and just use threading
。
thread
和 threading
模块的用途完全不同。 thread
模块是一个用 C 编写的低级模块,旨在抽象出平台差异并提供 最小 跨平台原语集(本质上是线程和简单锁) 可以作为更高级别 API 的基础。如果您将 Python 移植到不支持现有线程 API 的新平台(例如 POSIX 线程),那么您必须编辑 thread
模块源代码,以便您可以包装适当的 OS 级调用以在您的新平台上提供相同的原语。
例如,如果您查看当前的 CPython 实现,您会看到 Python Lock
基于未命名的 POSIX Linux 上的信号量,POSIX 条件变量和 OS X 上的 POSIX 互斥锁的组合(不支持未命名的信号量),以及Event
和 Windows 特定库调用的集合,在 Windows 上提供各种原子操作。作为 Python 用户,您不想关心这些细节。 thread
模块提供了抽象层,让您可以构建更高级别的代码,而无需担心平台级别的细节。
因此,thread
模块确实是为开发 Python 的人提供便利,而不是为使用它的人提供便利:它不是普通 Python 用户所期望的东西需要处理。出于这个原因,该模块已在 Python 3 中重命名为 _thread
:前导下划线表示它是私有的,用户不应依赖其 API 或未来的行为。
相比之下,threading
-模块是一个用Python编写的受Java启发的模块。它建立在 thread
模块奠定的基础上,为启动和加入线程提供了方便的 API,并提供了广泛的并发原语集(可重入锁、事件、条件变量、信号量、屏障等等)给用户。这几乎总是您作为 Python 用户想要使用的模块。如果您对幕后发生的事情感兴趣,值得花一些时间看看 threading
source:您可以看到 threading
模块如何从 [=11] 中提取它需要的原语=] 模块并将所有内容放在一起以提供更高级别的 API.
请注意,从 Python 核心开发人员的角度来看,这里有不同的权衡。一方面,将 Python 移植到新平台应该很容易,因此 thread
模块应该很小:你应该只需要实现一些基本原语就可以起床和 运行 在你的新平台上。相比之下,Python 用户 需要各种各样的并发原语,因此 threading
库需要扩展才能支持这些用户的需求。将线程功能拆分为两个单独的层是提供用户所需的好方法,同时又不会在各种平台上不必要地难以维护 Python。
回答你的具体问题:如果你必须直接使用thread
库(尽管我上面已经说过),你可以这样做:
import thread
import time
def main():
t1=thread.start_new_thread(prints,(3,))
t2=thread.start_new_thread(prints,(5,))
def prints(i):
while(i>0):
print "i="+str(i)+"\n"
i=i-1
if __name__=='__main__':
main()
# Give time for the output to show up.
time.sleep(1.0)
但是,当然,使用 time.sleep
是在主线程中处理事情的一种非常拙劣的方式:实际上,我们想等到两个子线程都完成它们的工作后再退出。所以我们需要构建一些功能,让主线程可以等待子线程。该功能并不直接存在于 thread
模块中,但它存在于 threading
中:这正是 threading
模块的要点:它提供了丰富、易于使用的 API 代替最小的、难以使用的 thread
API。所以我们回到总结行:不要使用 thread
,使用 threading
.
我现在很喜欢线程并探索线程和线程库。当我开始使用它们时,我编写了 2 个基本程序。以下是 2 个程序及其相应的输出:
threading_1.py :
import threading
def main():
t1=threading.Thread(target=prints,args=(3,))
t2=threading.Thread(target=prints,args=(5,))
t1.start()
t2.start()
t1.join()
t2.join()
def prints(i):
while(i>0):
print "i="+str(i)+"\n"
i=i-1
if __name__=='__main__':
main()
输出:
i=3
i=2
i=5
i=4
i=1
i=3
i=2
i=1
thread_1.py
import thread
import threading
def main():
t1=thread.start_new_thread(prints,(3,))
t2=thread.start_new_thread(prints,(5,))
t1.start()
t2.start()
t1.join()
t2.join()
def prints(i):
while(i>0):
print "i="+str(i)+"\n"
i=i-1
if __name__=='__main__':
main()
输出:
Traceback (most recent call last):
i=3
File "thread_1.py", line 19, in <module>
i=2
i=1
main()
i=5
i=4
i=3
i=2
i=1
File "thread_1.py", line 8, in main
t1.start()
AttributeError: 'int' object has no attribute 'start'
我想要的输出与 threading_1.py 中的一样,其中交错打印使它成为一个令人信服的线程执行示例。我的理解是 "threading" 与 [=38= 相比 higher-class library ]。而我进入 thread_1.py 的 AttributeError 是因为我在从线程库启动的线程上运行而不是线程。
所以,现在我的问题是 - 如何使用 thread_1.py 实现类似于 threading_1.py 的输出。是否可以修改或调整程序以产生相同的结果?
简短回答:忽略 thread
module and just use threading
。
thread
和 threading
模块的用途完全不同。 thread
模块是一个用 C 编写的低级模块,旨在抽象出平台差异并提供 最小 跨平台原语集(本质上是线程和简单锁) 可以作为更高级别 API 的基础。如果您将 Python 移植到不支持现有线程 API 的新平台(例如 POSIX 线程),那么您必须编辑 thread
模块源代码,以便您可以包装适当的 OS 级调用以在您的新平台上提供相同的原语。
例如,如果您查看当前的 CPython 实现,您会看到 Python Lock
基于未命名的 POSIX Linux 上的信号量,POSIX 条件变量和 OS X 上的 POSIX 互斥锁的组合(不支持未命名的信号量),以及Event
和 Windows 特定库调用的集合,在 Windows 上提供各种原子操作。作为 Python 用户,您不想关心这些细节。 thread
模块提供了抽象层,让您可以构建更高级别的代码,而无需担心平台级别的细节。
因此,thread
模块确实是为开发 Python 的人提供便利,而不是为使用它的人提供便利:它不是普通 Python 用户所期望的东西需要处理。出于这个原因,该模块已在 Python 3 中重命名为 _thread
:前导下划线表示它是私有的,用户不应依赖其 API 或未来的行为。
相比之下,threading
-模块是一个用Python编写的受Java启发的模块。它建立在 thread
模块奠定的基础上,为启动和加入线程提供了方便的 API,并提供了广泛的并发原语集(可重入锁、事件、条件变量、信号量、屏障等等)给用户。这几乎总是您作为 Python 用户想要使用的模块。如果您对幕后发生的事情感兴趣,值得花一些时间看看 threading
source:您可以看到 threading
模块如何从 [=11] 中提取它需要的原语=] 模块并将所有内容放在一起以提供更高级别的 API.
请注意,从 Python 核心开发人员的角度来看,这里有不同的权衡。一方面,将 Python 移植到新平台应该很容易,因此 thread
模块应该很小:你应该只需要实现一些基本原语就可以起床和 运行 在你的新平台上。相比之下,Python 用户 需要各种各样的并发原语,因此 threading
库需要扩展才能支持这些用户的需求。将线程功能拆分为两个单独的层是提供用户所需的好方法,同时又不会在各种平台上不必要地难以维护 Python。
回答你的具体问题:如果你必须直接使用thread
库(尽管我上面已经说过),你可以这样做:
import thread
import time
def main():
t1=thread.start_new_thread(prints,(3,))
t2=thread.start_new_thread(prints,(5,))
def prints(i):
while(i>0):
print "i="+str(i)+"\n"
i=i-1
if __name__=='__main__':
main()
# Give time for the output to show up.
time.sleep(1.0)
但是,当然,使用 time.sleep
是在主线程中处理事情的一种非常拙劣的方式:实际上,我们想等到两个子线程都完成它们的工作后再退出。所以我们需要构建一些功能,让主线程可以等待子线程。该功能并不直接存在于 thread
模块中,但它存在于 threading
中:这正是 threading
模块的要点:它提供了丰富、易于使用的 API 代替最小的、难以使用的 thread
API。所以我们回到总结行:不要使用 thread
,使用 threading
.