网站性能检测评分
注:本网站页面html检测工具扫描网站中存在的基本问题,仅供参考。
python中threading
python用正则爬取豆瓣电影排行榜,连老司机都不知道的奥秘 互联网视频课程
使用了tkinter做了简单页面
首先分析要爬取的url, 发现每个页面有25条内容, 总共有十页, 第一页的URL为https://movie.douban/top250?start=0&filter=
第二页的url为https://movie.douban/top250?start=25&filter=
第三页第四页也是类似的URL, 只是修改了start后面的数字, 第一页是0, 往后每增加25, 所以url的格式为https://movie.douban/top250?start=+{ID}
然后分析如何爬取内容:
首先爬取标题:
查看源代码后, 发现标题是放在这样的代码:
肖申克的救赎 / The Shawshank Redemption / 月黑高飞(港) / 刺激1995(台)12345发现电影的名称一般都放在
电影名称1这样的标记对中, 所以根据这个可以写出正则表达式:
(.*?)1不过在后面的测试中发现这样写的话, 每个电影名称能获取两个信息
肖申克的救赎 / The Shawshank Redemption12显然第二条信息不是我们想要的, 经过对比发现第二条信息中都会有两个空格的代码, 所以把&给过滤掉就可以了:
(.[^&]*?)1接下来爬取评分, 评分一般放在这样的代码中:
716019人评价
123456这个正则就很好写了:"v:average">(.*?)1这样就ok啦, 这个程序还是非常简单的, 上源代码:
# -*- coding: utf-8 -*-from Tkinter import *from ScrolledText import ScrolledTextimport requests, re, threadingdef replite(ID): varl.set('正在获取第%d页内容' % (ID / 25 + 1)) html = 'https://movie.douban/top250?start=' + str(ID) response = requests.get(html).text # response = unicode(response, 'GBK').encode('UTF-8') response = response.encode('utf-8 ') # print response # reg = r'(.*?).*?"v:average">(.*?)' regTitle = r'(.[^&]*?)' regStars = r'.*?"v:average">(.*?)' regTitle = repile(regTitle) regStars = repile(regStars) titles = re.findall(regTitle, response) stars = re.findall(regStars, response) info = list(zip(titles, stars)) return infodef write(): varl.set('开始爬取内容') ID = 0 nums = 1 while ID < 250: res = replite(ID) ID += 25 for each in res: text.insert(END, 'No.%d\t%-30s%s分\n' % (nums, each[0], each[1])) nums += 1 varl.set('获取内容成功')def start(): t1 = threading.Thread(target=write) t1.start()def save(): content = text.get("0.0", "end").encode('GBK') textfile = open(u'E:\\豆瓣电影排行250.txt', 'w') textfile.write(content) textfile.close()root = Tk()root.title('豆瓣电影top250')root.geometry('820x500+400+200')text = ScrolledText(root, font=('楷体', 15), width=80, height=20)text.grid()frame = Frame(root)frame.grid()# 启动爬虫功能startButton = Button(frame, text='开始', font=('楷体', 18), command=start)startButton.grid()startButton.pack(side=LEFT)# 保存爬取信息saveButton = Button(frame, text='保存文件', font=('楷体', 18), command=save)saveButton.grid()saveButton.pack(side=LEFT)# 退出程序exitButton = Button(frame, text='退出', font=('楷体', 18), command=frame.quit)exitButton.grid()exitButton.pack(side=LEFT)varl = StringVar()info_label = Label(root, fg='red', textvariable=varl)info_label.grid()varl.set('准备中....')root.mainloop()
下面给大家分享python正则详解:
正则表达式是一个很强大的字符串处理工具,几乎任何关于字符串的操作都可以使用正则表达式来完成,作为一个爬虫工作者,每天和字符串打交道,正则表达式更是不可或缺的技能,正则表达式的在不同的语言中使用方式可能不一样,不过只要学会了任意一门语言的正则表达式用法,其他语言中大部分也只是换了个函数的名称而已,本质都是一样的。下面,我来介绍一下python中的正则表达式是怎么使用的。
首先,python中的正则表达式大致分为以下几部分:
元字符模式函数re 内置对象用法分组用法环视用法 所有关于正则表达式的操作都使用 python 标准库中的 re 模块。
一、元字符 (参见 python 模块 re 文档)
. 匹配任意字符(不包括换行符)^ 匹配开始位置,多行模式下匹配每一行的开始$ 匹配结束位置,多行模式下匹配每一行的结束* 匹配前一个元字符0到多次+ 匹配前一个元字符1到多次? 匹配前一个元字符0到1次{m,n} 匹配前一个元字符m到n次\\ 转义字符,跟在其后的字符将失去作为特殊元字符的含义,例如\\.只能匹配.,不能再匹配任意字符[] 字符集,一个字符的集合,可匹配其中任意一个字符| 逻辑表达式 或 ,比如 a|b 代表可匹配 a 或者 b(...) 分组,默认为捕获,即被分组的内容可以被单独取出,默认每个分组有个索引,从 1 开始,按照"("的顺序决定索引值(?iLmsux) 分组中可以设置模式,iLmsux之中的每个字符代表一个模式,用法参见 模式 I(?:...) 分组的不捕获模式,计算索引时会跳过这个分组(?P I IGNORECASE, 忽略大小写的匹配模式, 样例如下 s = 'hello World!'regex = repile("hello world!", re.I)print regex.match(s).group()#output> 'Hello World!'#在正则表达式中指定模式以及注释regex = repile("(?#注释)(?i)hello world!")print regex.match(s).group()#output> 'Hello World!' L LOCALE, 字符集本地化。这个功能是为了支持多语言版本的字符集使用环境的,比如在转义符\w,在英文环境下,它代表[a-zA-Z0-9_],即所以英文字符和数字。如果在一个法语环境下使用,缺省设置下,不能匹配"é" 或 "04"。加上这L选项和就可以匹配了。不过这个对于中文环境似乎没有什么用,它仍然不能匹配中文字符。M MULTILINE,多行模式, 改变 ^ 和 $ 的行为 s = '''first linesecond linethird line'''# ^regex_start = repile("^\w+")print regex_start.findall(s)# output> ['first']regex_start_m = repile("^\w+", re.M)print regex_start_m.findall(s)# output> ['first', 'second', 'third']#$regex_end = repile("\w+$")print regex_end.findall(s)# output> ['line']regex_end_m = repile("\w+$", re.M)print regex_end_m.findall(s)# output> ['line', 'line', 'line'] S DOTALL,此模式下 '.' 的匹配不受限制,可匹配任何字符,包括换行符 s = '''first linesecond linethird line'''#regex = repile(".+")print regex.findall(s)# output> ['first line', 'second line', 'third line']# re.Sregex_dotall = repile(".+", re.S)print regex_dotall.findall(s)# output> ['first line\nsecond line\nthird line'] X VERBOSE,冗余模式, 此模式忽略正则表达式中的空白和#号的注释,例如写一个匹配邮箱的正则表达式email_regex = repile("[\w+\.]+@[a-zA-Z\d]+\.(com|cn)")email_regex = repile("""[\w+\.]+ # 匹配@符前的部分 @ # @符 [a-zA-Z\d]+ # 邮箱类别 \.(com|cn) # 邮箱后缀 """, re.X)U UNICODE,使用 \w, \W, \b, \B 这些元字符时将按照 UNICODE 定义的属性.正则表达式的模式是可以同时使用多个的,在 python 里面使用按位或运算符 | 同时添加多个模式 如 repile('', re.I|re.M|re.S) 每个模式在 re 模块中其实就是不同的数字 print re.I# output> 2print re.L# output> 4print re.M# output> 8print re.S# output> 16print re.X# output> 64print re.U# output> 32四、re 内置对象用法 SRE_Pattern 这个对象是一个编译后的正则表达式,编译后不仅能够复用和提升效率,同时也能够获得一些其他的关于正则表达式的信息属性: flags 编译时指定的模式groupindex 以正则表达式中有别名的组的别名为键、以该组对应的编号为值的字典,没有别名的组不包含在内。groups 正则表达式中分组的数量 pattern 编译时用的正则表达式s = 'Hello, Mr.Gumby : 2016/10/26'p = repile('''(?: # 构造一个不捕获分组 用于使用 | (?P 好了,今天的知识就分享到这里,欢迎关注爱编程的南风,私信关键词:学习资料,获取更多学习资源,如果文章对你有有帮助,请收藏关注,在今后与你分享更多学习python的文章。同时欢迎在下面评论区留言如何学习python。
Python代码风格:PEP8规则 笔记 互联网视频课程
Python程序设计的代码风格应该遵循PEP8规则:
一、代码布局
1、缩进:
每级缩进4个空格(不用Tab,更不空格Tab混用)
1、续行应该与其包裹元素对齐,要么使用圆括号、方括号和花括号内的隐式行连接来垂直对齐,要么使用悬挂式缩进对齐。当使用悬挂缩进时,应该考虑到第一行不应该有参数,以及使用缩进以区分自己是续行。
2、缩进4个空格的规则对于续行是可选的。
3、当 if 语句的条件部分长到需要换行写的时候,注意可以在两个字符关键字的连接处(比如 if ),增加一个空格,再增加一个左括号来创造一个4空格缩进的多行条件。这会与 if 语句内同样使用4空格缩进的代码产生视觉冲突。PEP没有明确指明要如何区分i发的条件代码和内嵌代码。可使用的选项包括但不限于下面几种情况:
4、(可以参考下面关于是否在二进制运算符之前或之后截断的讨论)
在多行结构中的大括号/中括号/小括号的右括号可以与内容对齐单独起一行作为最后一行的第一个字符,如:
或者也可以与多行结构的第一行第一个字符对齐,如:
2、Tab还是空格?
空格是被首先推荐的缩进方式。
Tab应该只在现有代码已经使用tab进行缩进的情况下使用,以便和现有代码保持一致。
Python 3不允许再同一个代码块中Tab和空格混合使用。
混合使用制表符和空格缩进的Python2代码应该统一转成空格。
使用命令行运行Python 2时,使用-t选项,会出现非法混用tab和空格的警告。当使用-tt选项时,这些警告会变成错误。强烈推荐使用这些选项!
3、最大行长
每行最大长度79个字符。
对于连续大段的文字(比如文档字符串(docstring)或注释),每行应该被限制在72个字符长度内。
Python标准库比较传统,将行长限制在79个字符以内(文档字符串/注释为72个字符)。
一种推荐的换行方式是利用Python圆括号、方括号和花括号中的隐式续行。长行可以通过在括号内换行来分成多行。应该最好加上反斜杠来区别续行。
有时续行只能使用反斜杠才。例如,较长的多个 with 语句不能采用隐式续行,只能接受反斜杠表示换行:
另一个这样的例子是assert语句。要确保续行的缩进适当。
在二元运算符之前应该换行吗?
遵循数学的传统能产出更多可读性高的代码:
4、空行
顶层函数和类的定义,前后用两个空行隔开。
类里的方法定义用一个空行隔开。
相关的功能组可以用额外的空行(尽量少地)隔开。一堆相关的单行代码之间的空白行可以省略(例如,一组虚拟实现 dummy implementations)。
在函数中使用空行来区分逻辑段(尽量少地)。
Python接受control-L(即^L)换页符作为空格;许多工具把这些字符当作页面分隔符,所以你可以在文件中使用它们来分隔相关段落。请注意,一些编辑器和基于Web的代码阅读器可能无法识别control-L为换页,将在其位置显示另一个字形。
5、源文件编码
Python核心发布版本中的代码总是以UTF-8格式编码(或者在Python2中用ASCII编码)。
使用ASCII(Python 2)或者UTF-8(Python 3)的文件不应该添加编码声明。
在标准库中,只有用作测试目的,或者注释或文档字符串需要提及作者名字而不得不使用非ASCII字符时,才能使用非默认的编码。否则,在字符串文字中包括非ASCII数据时,推荐使用\x, \u, U或N等转义符。
对于Python 3.0及其以后的版本中,标准库遵循以下原则(参见PEP 3131):Python标准库中的所有标识符都必须只采用ASCII编码的标识符,在可行的条件下也应当使用英文词(很多情况下,使用的缩写和技术术语词都不是英文)。此外,字符串文字和注释应该只包括ASCII编码。只有两种例外:
(a) 测试情况下为了测试非ASCII编码的特性
(b) 作者名字。作者名字不是由拉丁字母组成的也必须提供一个拉丁音译名。
鼓励面向全球的开源项目都采用类似的原则。
6、导入
1、imports应该分行写,而不是都写在一行,例如:
这样写也是可以的:
导入(import)始终在文件的顶部,在模块注释和文档字符串之后,在模块全局变量和常量之前。
导入顺序如下:
imports应该按照下面的顺序分组来写:
1、标准库imports
2、相关第三方imports
3、本地应用/库的特定imports
不同组的imports之前用空格隔开。
将任何相关的 __all__ 说明(specification)放在imports之后。
推荐使用绝对(absolute)imports,因为这样通常更易读,在import系统没有正确配置的情况下,也会有更好的表现(或者至少会给出错误信息):
在绝对路径比较长的情况下,也可以使用相对导入:
Python 3中已经禁止隐式的相对导入。
导入类的方法,通常可以这样写:
如果和本地命名的拼写产生了冲突,应当使用绝对导入:
禁止使用通配符导入。
通配符导入(from import *)应该避免,因为它不清楚命名空间有哪些名称存,混淆读者和许多自动化的工具。唯一的例外是重新发布对外的API时可以考虑使用。
7、模块中前后具有双下划线的变量名
像__all__ , __author__ , __version__ 等这样的模块中的变量名(也就是名字里有两个前缀下划线和两个后缀下划线),应该放在文档字符串的后面,以及除from __future__ 之外的import表达式前面。Python要求将来在模块中的导入,必须出现在除文档字符串之外的其他代码之前。
比如:
二、字符串引号
Python中单引号字符串和双引号字符串都是相同的。注意尽量避免在字符串中的反斜杠以提高可读性。
根据PEP 257, 三个引号都使用双引号。
三、表达式和语句中的空格
在下列情况下,避免使用无关的空格:
1、紧跟在小括号,中括号或者大括号后。
2、紧贴在逗号、分号或者冒号之前。
3、然而,冒号在切片中就像二元运算符,在两边应该有相同数量的空格(把它当做优先级最低的操作符)。在扩展的切片操作中,所有的冒号必须有相同的间距。例外情况:当一个切片参数被省略时,空格就被省略了。
4、紧贴在函数参数的左括号之前。
5、紧贴索引或者切片的左括号之前。
6、为了和另一个赋值语句对齐,在赋值运算符附件加多个空格。
其他建议
1、避免在尾部添加空格。因为尾部的空格通常都看不见,会产生混乱:比如,一个反斜杠后面跟一个空格的换行符,不算续行标记。有些编辑器不会保留尾空格,并且很多项目(像CPython)在pre-commit的挂钩调用中会过滤掉尾空格。
总是在二元运算符两边加一个空格:赋值(=),增量赋值(+=,-=),比较(==,,!=,,=,in,not,in,is,is not),布尔(and, or, not)。
如果使用具有不同优先级的运算符,请考虑在具有最低优先级的运算符周围添加空格。有时需要通过自己来判断;但是,不要使用一个以上的空格,并且在二元运算符的两边使用相同数量的空格。
2、在指定函数 关键字参数 或者 默认参数 值的时候,不要在=附近加上空格。
3、功能型注释应该使用冒号的一般性规则,并且在使用 ->的时候要在两边加空格。(参考下面的功能注释得到能够多信息)
4、当给有类型备注的参数赋值的时候,在=两边添加空格(仅针对那种有类型备注和默认值的参数)。
5、复合语句(同一行中的多个语句)通常是不允许的。
6、虽然有时候将小的代码块和 if/for/while 放在同一行没什么问题,多行语句块的情况不要这样用,同样也要避免代码行太长!
四、注释
与代码自相矛盾的注释比没注释更差。修改代码时要优先更新注释!
注释是完整的句子。如果注释是断句,首字母应该大写,除非它是小写字母开头的标识符(永远不要修改标识符的大小写)。
如果注释很短,可以省略末尾的句号。注释块通常由一个或多个段落组成。段落由完整的句子构成且每个句子应该以点号(后面要有两个空格)结束,并注意断词和空格。
非英语国家的程序员请用英语书写你的注释,除非你120%确信代码永远不会被不懂你的语言的人阅读。
1、注释块
注释块通常应用在代码前,并和这些代码有同样的缩进。每行以 '# '(除非它是注释内的缩进文本,注意#后面有空格)。
注释块内的段落用仅包含单个 '#' 的行分割。
2、行内注释
慎用行内注释(Inline Comments) 节俭使用行内注释。 行内注释是和语句在同一行,至少用两个空格和语句分开。行内注释不是必需的,重复罗嗦会使人分心。
不推荐:
但是有时,很有必要:
加了以后对理解代码很有帮助的情况下,关键处才加。
3、文档字符串
文档字符串的标准参见:PEP 257。
为所有公共模块、函数、类和方法书写文档字符串。非公开方法不一定有文档字符串,建议有注释(出现在 def 行之后)来描述这个方法做什么。
更多参考:PEP 257 文档字符串约定。注意结尾的 """ 应该单独成行,例如:
单行的文档字符串,结尾的 """ 在同一行。
4、版本标签
如果你必须在源文件中包含git、Subversion、CVS或RCS crud信息,放置在模块的文档字符串之后,任何其他代码之前,上下各用一个空行:
五、命名规范
Python库的命名约定有点混乱,不可能完全一致。但依然有些普遍推荐的命名规范的。新的模块和包 (包括第三方的框架) 应该遵循这些标准。对不同风格的已有的库,建议保持内部的一致性。
1、最重要的原则
用户可见的API命名应遵循使用约定而不是实现。
2、命名风格
以下是常见的命名方式:
b(单个小写字母)
B(单个大写字母)
lowercase (小写字母)
lower_case_with_underscores (使用下划线分隔的小写字母)
UPPERCASE( 大写字母)
UPPER_CASE_WITH_UNDERSCORES (使用下划线分隔的大写字母)
CapitalizedWords(首字母大写的单词串或驼峰缩写)
注意: 使用大写缩写时,缩写使用大写字母更好。故 HTTPServerError 比 HttpServerError 更好。
mixedCase(不同于首字母大写,第一个单词的首字母小写)
Capitalized_Words_With_Underscores(带下划线,首字母大写,巨丑无比)
还有一种风格使用短前缀分组名字。这在Python中不常用, 但出于完整性提一下。例如,os.stat()返回的元组有st_mode, st_size, st_mtime等等这样的名字(与POSIX系统调用结构体一致)。
X11库的所有公开函数以X开头, Python中通常认为是不必要的,因为属性和方法名有对象作前缀,而函数名有模块名为前缀。
下面讲述首尾有下划线的情况:
_single_leading_underscore:(单前置下划线): 弱内部使用标志。 例如"from M import " 不会导入以下划线开头的对象。
single_trailing_underscore_(单后置下划线): 用于避免与 Python关键词的冲突。 例如:
__double_leading_underscore(双前置下划线): 当用于命名类属性,会触发名字重整。 (在类FooBar中,__boo变成 _FooBar__boo)。
__double_leading_and_trailing_underscore__(双前后下划线):用户名字空间的魔法对象或属性。例如:__init__ , __import__ or __file__,不要自己发明这样的名字。
3、命名约定规范
避免采用的名字:
决不要用字符'l'(小写字母el),'O'(大写字母oh),或 'I'(大写字母eye) 作为单个字符的变量名。一些字体中,这些字符不能与数字1和0区别。用'L' 代替'l'时。
包和模块名:
模块名要简短,全部用小写字母,可使用下划线以提高可读性。包名和模块名类似,但不推荐使用下划线。
模块名对应到文件名,有些文件系统不区分大小写且截短长名字,在 Unix上不是问题,但当把代码迁移到 Mac、Windows 或 DOS 上时,就可能是个问题。当然随着系统的演进,这个问题已经不是经常出现。
另外有些模块底层用C或C++ 书写,并有对应的高层Python模块,C/C++模块名有一个前置下划线 (如:_socket)。
类名:
遵循CapWord。
接口需要文档化并且可以调用时,可能使用函数的命名规则。
注意大部分内置的名字是单个单词(或两个),CapWord只适用于异常名称和内置的常量。
异常名:
如果确实是错误,需要在类名添加后缀 "Error"。
全局变量名:
变量尽量只用于模块内部,约定类似函数。
对设计为通过 "from M import " 来使用的模块,应采用 __all__ 机制来防止导入全局变量;或者为全局变量加一个前置下划线。
函数名:
函数名应该为小写,必要时可用下划线分隔单词以增加可读性。 mixedCase(混合大小写)仅被允许用于兼容性考虑(如: threading.py)。
函数和方法的参数:
实例方法第一个参数是 'self'。
类方法第一个参数是 'cls'。
如果函数的参数名与保留关键字冲突,通常在参数名后加一个下划线。
方法名和实例变量:
同函数命名规则。
非公开方法和实例变量增加一个前置下划线。
为避免与子类命名冲突,采用两个前置下划线来触发重整。类Foo属性名为__a, 不能以 Foo.__a访问。(执著的用户还是可以通过Foo._Foo__a。) 通常双前置下划线仅被用来避免与基类的属性发生命名冲突。
常量:
<...TENG讯资料整理!T2.1工程师 Python-threading 流量视频课程
threading 模块提供的常用方法:
threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
threading模块提供的类:
Thread, Lock, Rlock, Condition, [Bounded]Semaphore, Event, Timer, local.
Thread
Thread是线程类,与Java类似,有两种使用方法,直接传入要运行的方法或从Thread继承并覆盖run():
构造方法:
Thread(group=None, target=None, name=None, args=(), kwargs={})
group: 线程组,目前还没有实现,库引用中提示必须是None;
target: 要执行的方法;
name: 线程名;
args/kwargs: 要传入方法的参数。
后续继续介绍欢迎关注小编
Python并发编程之线程中的信息隔离 流量视频课程
上班第二天,大家应该比较忙吧。编编也是呢,所以今天的内容也很少。只要几分钟就能学完。昨天我们说,线程与线程之间要通过消息通信来控制程序的执行。讲完了消息通信,今天就来探讨下线程里的 信息隔离是如何做到的。
大家注意:
信息隔离,这并不是官方命名的名词,也不是网上广为流传的名词。是我为了方便理解而自创的,大家知道就好咯。
本文目录
初步认识信息隔离信息隔离的意义何在
. 初步认识信息隔离
什么是 信息隔离?比如说,咱有两个线程,线程A里的变量,和线程B里的变量值不能共享。这就是 信息隔离 。你可能要说,那变量名取不一样不就好啦?是的,如果所有的线程都不是由一个class实例化出来的同一个对象,确实是可以。这个问题我们暂且挂着,后面我再说明。那么,如何实现 信息隔离 呢?在Python中,其提供了 threading.local这个类,可以很方便的控制变量的隔离,即使是同一个变量,在不同的线程中,其值也是不能共享的。用代码来看下
从输出来看,我们可以知道, local实际是一个 字典型的对象,其内部可以以 key-value 的形式存入你要做信息隔离的变量。local实例可以是 全局唯一 的,只有一个。因为你在给local存入或访问变量时,它会根据当前的线程的不同从不同的 存储空间 存入或获取。基于此,我们可以得出以下三点结论:
主线程中的变量,不会因为其是全局变量,而被子线程获取到;主线程也不能获取到子线程中的变量;子线程与子线程之间的变量也不能互相访问。
所以如果想在当前线程保存一个全局值,并且各自线程(包括主线程)互不干扰,使用local类吧。
. 信息隔离的意义何在
细心的你,一定已经发现了,上面那个例子,即使我们不用 threading.local来做信息隔离,两个线程 self.getName()本身就是隔离的,没有任何关系的。因为这两个线程是由一个class实例出的两个不同的实例对象。自然是可以不用做隔离,因为其本身就是隔离的。
但是,现实开发中。不可排除有多个线程,是由一个class实例出的同一个实例对象而实现的。
譬如,现在新手特别喜欢的爬虫项目。通常都是先给爬虫一个主页,然后获取主页下的所有链接,对这个链接再进行遍历,一直往下,直到把所有的链接都爬完,获取到我们所需的内容。
由于单线程的爬取效率实在是太低了,我们考虑使用多线程来工作。先使用 socket和
建立一个TCP连接。然后在这个连接的基础上,对主页上的每个链接(我们这里举这两个例子)创建一个线程,这样效率就高多了。友情提醒:以下代码,若要理解,可能需要你了解下socket的网络编程相关内容。我在前几天的文章中有发布一篇相关的文章,没有基础的同学可以先去看看那篇文章。
输出结果
如果是在这种场景下,要做到线程之间的状态信息的隔离,就肯定要借助 threading.local,所以 threading.local的存在是有存在的意义的。其他还有很多场景是必须借助 threading.local才能实现的,而这些就要靠你们在真正的业务开发中去发现咯。
python核心编程之多线程教程-threading 营销视频课程
多线程-threading
python的thread模块是比较底层的模块,python的threading模块是对thread做了一些包装的,可以更加方便的被使用
1. 使用threading模块
单线程执行
#coding=utf-8
import time
def saySorry():
print("亲爱的,我错了,我能吃饭了吗?")
time.sleep(1)
if __name__ == "__main__":
for i in range(5):
saySorry()
运行结果:
多线程执行
#coding=utf-8
import threading
import time
def saySorry():
print("亲爱的,我错了,我能吃饭了吗?")
time.sleep(1)
if __name__ == "__main__":
for i in range(5):
t = threading.Thread(target=saySorry)
t.start() #启动线程,即让线程开始执行
运行结果:
说明
可以明显看出使用了多线程并发的操作,花费时间要短很多
创建好的线程,需要调用start()方法来启动
2. 主线程会等待所有的子线程结束后才结束
#coding=utf-8
import threading
from time import sleep,ctime
def sing():
for i in range(3):
print("正在唱歌...%d"%i)
sleep(1)
def dance():
for i in range(3):
print("正在跳舞...%d"%i)
sleep(1)
if __name__ == '__main__':
print('---开始---:%s'%ctime())
t1 = threading.Thread(target=sing)
t2 = threading.Thread(target=dance)
t1.start()
t2.start()
#sleep(5) # 屏蔽此行代码,试试看,程序是否会立马结束?
print('---结束---:%s'%ctime())
3. 查看线程数量
#coding=utf-8
import threading
from time import sleep,ctime
def sing():
for i in range(3):
print("正在唱歌...%d"%i)
sleep(1)
def dance():
for i in range(3):
print("正在跳舞...%d"%i)
sleep(1)
if __name__ == '__main__':
print('---开始---:%s'%ctime())
t1 = threading.Thread(target=sing)
t2 = threading.Thread(target=dance)
t1.start()
t2.start()
while True:
length = len(threading.enumerate())
print('当前运行的线程数为:%d'%length)
if length<=1:
break
sleep(0.5)
python核心编程之多线程教程-threading注意点 公司视频课程
threading注意点
1. 线程执行代码的封装
通过上一小节,能够看出,通过使用threading模块能完成多任务的程序开发,为了让每个线程的封装性更完美,所以使用threading模块时,往往会定义一个新的子类class,只要继承threading.Thread就可以了,然后重写run方法
示例如下:
#coding=utf-8
import threading
import time
class MyThread(threading.Thread):
def run(self):
for i in range(3):
time.sleep(1)
msg = "I'm "+self.name+' @ '+str(i) #name属性中保存的是当前线程的名字
print(msg)
if __name__ == '__main__':
t = MyThread()
t.start()
说明
python的threading.Thread类有一个run方法,用于定义线程的功能函数,可以在自己的线程类中覆盖该方法。而创建自己的线程实例后,通过Thread类的start方法,可以启动该线程,交给python虚拟机进行调度,当该线程获得执行的机会时,就会调用run方法执行线程。
2. 线程的执行顺序
#coding=utf-8
import threading
import time
class MyThread(threading.Thread):
def run(self):
for i in range(3):
time.sleep(1)
msg = "I'm "+self.name+' @ '+str(i)
print(msg)
def test():
for i in range(5):
t = MyThread()
t.start()
if __name__ == '__main__':
test()
执行结果:(运行的结果可能不一样,但是大体是一致的)
I'm Thread-1 @ 0
I'm Thread-2 @ 0
I'm Thread-5 @ 0
I'm Thread-3 @ 0
I'm Thread-4 @ 0
I'm Thread-3 @ 1
I'm Thread-4 @ 1
I'm Thread-5 @ 1
I'm Thread-1 @ 1
I'm Thread-2 @ 1
I'm Thread-4 @ 2
I'm Thread-5 @ 2
I'm Thread-2 @ 2
I'm Thread-1 @ 2
I'm Thread-3 @ 2
说明
从代码和执行结果我们可以看出,多线程程序的执行顺序是不确定的。当执行到sleep语句时,线程将被阻塞(Blocked),到sleep结束后,线程进入就绪(Runnable)状态,等待调度。而线程调度将自行选择一个线程执行。上面的代码中只能保证每个线程都运行完整个run函数,但是线程的启动顺序、run函数中每次循环的执行顺序都不能确定。
3. 总结
每个线程一定会有一个名字,尽管上面的例子中没有指定线程对象的name,但是python会自动为线程指定一个名字。
当线程的run()方法结束时该线程完成。
无法控制线程调度程序,但可以通过别的方式来影响线程调度的方式。
线程的几种状态
Python多线程threading—图片下载 公司视频课程
上一篇,写了一个爬壁纸图片的小爬虫:Python爬虫入门—图片下载下载效果太慢了,于是乎想到了用多线程改造一下,看看速度能提高多少!
虽然说,由于GIL锁(Global Interpreter Lock)的存在,Python的多线程不是真正意义上的多线程,一个时间段内,一个CPU只能执行一个线程。但是在爬虫相关的程序上,经常出现IO密集型任务多CPU密集型任务少的情况,大多数时间都在等get、post请求、收发数据(对于本次的爬虫图片下载程序,更是如此)。于是可以用Python的多线程来实现加速,即一个线程在get、post或等数据传输时,不必停止整个程序,而是切换到其他的线程完成接下来的任务。这样,本质上单线程的Python也能实现多线程的效果~
关于多进程和多线程,墙裂推荐廖雪峰的:
进程和线程liaoxuefeng
还有这篇文章:
tonnie:从0到1,Python异步编程的演进之路zhuanlan.zhihu
我们以关键词‘pig’为例,可以搜到77张相关图片,然后,让我们来做一下对比测试,比较下原始单线程代码和多线程代码下载速度的差异~
改造前,单线程的代码如下:
#_*_ coding:utf-8 _*_#__author__='阳光流淌007'#__date__2018-01-21'#爬取wallhaven上的的图片,支持自定义搜索关键词,自动爬取并该关键词下所有图片并存入本地电脑。import osimport requestsimport timeimport randomfrom lxml import etreekeyWord = input(f"{'Please input the keywords that you want to download :'}")class Spider(): #初始化参数 def __init__(self): #headers是请求头,"User-Agent"、"Accept"等字段可通过谷歌Chrome浏览器查找! self.headers = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.104 Safari/537.36", } #filePath是自定义的,本次程序运行后创建的文件夹路径,存放各种需要下载的对象。 self.filePath = ('/users/zhaoluyang/小Python程序集合/桌面壁纸/'+ keyWord + '/') def creat_File(self): #新建本地的文件夹路径,用于存储网页、图片等数据! filePath = self.filePath if not os.path.exists(filePath): os.makedirs(filePath) def get_pageNum(self): #用来获取搜索关键词得到的结果总页面数,用totalPagenum记录。由于数字是夹在形如:1,985 Wallpapers found for “dog”的string中, #所以需要用个小函数,提取字符串中的数字保存到列表numlist中,再逐个拼接成完整数字。。。 total = "" url = ("https://alpha.wallhaven.cc/search?q={}&categories=111&purity=100&sorting=relevance&order=desc").format(keyWord) html = requests.get(url) selector = etree.HTML(html.text) pageInfo = selector.xpath('//header[@class="listing-header"]/h1[1]/text()') string = str(pageInfo[0]) numlist = list(filter(str.isdigit,string)) for item in numlist: total += item totalPagenum = int(total) return totalPagenum def main_fuction(self): #count是总图片数,times是总页面数 self.creat_File() count = self.get_pageNum() print("We have found:{} images!".format(count)) times = int(count/24 + 1) j = 1 start = time.time() for i in range(times): pic_Urls = self.getLinks(i+1) start2 = time.time() for item in pic_Urls: self.download(item,j) j += 1 end2 = time.time() print('This page cost:',end2 - start2,'s') end = time.time() print('Total cost:',end - start,'s') def getLinks(self,number): #此函数可以获取给定numvber的页面中所有图片的链接,用List形式返回 url = ("https://alpha.wallhaven.cc/search?q={}&categories=111&purity=100&sorting=relevance&order=desc&page={}").format(keyWord,number) try: html = requests.get(url) selector = etree.HTML(html.text) pic_Linklist = selector.xpath('//a[@class="jsAnchor thumb-tags-toggle tagged"]/@href') except Exception as e: print(repr(e)) return pic_Linklist def download(self,url,count): #此函数用于图片下载。其中参数url是形如:https://alpha.wallhaven.cc/wallpaper/616442/thumbTags的网址 #616442是图片编号,我们需要用strip()得到此编号,然后构造html,html是图片的最终直接下载网址。 string = url.strip('/thumbTags').strip('https://alpha.wallhaven.cc/wallpaper/') html = 'http://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-' + string + '.jpg' pic_path = (self.filePath + keyWord + str(count) + '.jpg' ) try: start = time.time() pic = requests.get(html,headers = self.headers) f = open(pic_path,'wb') f.write(pic.content) f.close() end = time.time() print(f"Image:{count} has been downloaded,cost:",end - start,'s') except Exception as e: print(repr(e))spider = Spider()spider.main_fuction()
下载77张图片总耗时157.17749691009521 s
引入threading多线程模块后的程序代码如下:
#_*_ coding:utf-8 _*_#__author__='阳光流淌007'#__date__='2018-01-28'#爬取wallhaven上的的图片,支持自定义搜索关键词,自动爬取并该关键词下所有图片并存入本地电脑。import osimport requestsimport timefrom lxml import etreefrom threading import ThreadkeyWord = input(f"{'Please input the keywords that you want to download :'}")class Spider(): #初始化参数 def __init__(self): self.headers = {#headers是请求头,"User-Agent"、"Accept"等字段可通过谷歌Chrome浏览器查找! "User-Agent": "Mozilla/5.0(WindowsNT6.1;rv:2.0.1)Gecko/20100101Firefox/4.0.1", } self.proxies = {#代理ip,当网站限制ip访问时,需要切换访问ip"http": "http://61.178.238.122:63000", } #filePath是自定义的,本次程序运行后创建的文件夹路径,存放各种需要下载的对象。 self.filePath = ('/users/zhaoluyang/小Python程序集合/桌面壁纸/'+ keyWord + '/') def creat_File(self): #新建本地的文件夹路径,用于存储网页、图片等数据! filePath = self.filePath if not os.path.exists(filePath): os.makedirs(filePath) def get_pageNum(self): #用来获取搜索关键词得到的结果总页面数,用totalPagenum记录。由于数字是夹在形如:1,985 Wallpapers found for “dog”的string中, #所以需要用个小函数,提取字符串中的数字保存到列表numlist中,再逐个拼接成完整数字。。。 total = "" url = ("https://alpha.wallhaven.cc/search?q={}&categories=111&purity=100&sorting=relevance&order=desc").format(keyWord) html = requests.get(url,headers = self.headers,proxies = self.proxies) selector = etree.HTML(html.text) pageInfo = selector.xpath('//header[@class="listing-header"]/h1[1]/text()') string = str(pageInfo[0]) numlist = list(filter(str.isdigit,string)) for item in numlist: total += item totalPagenum = int(total) return totalPagenum def main_fuction(self): #count是总图片数,times是总页面数 self.creat_File() count = self.get_pageNum() print("We have found:{} images!".format(count)) times = int(count/24 + 1) j = 1 start = time.time() for i in range(times): pic_Urls = self.getLinks(i+1) start2 = time.time() threads = [] for item in pic_Urls: t = Thread(target = self.download, args = [item,j]) t.start() threads.append(t) j += 1 for t in threads: t.join() end2 = time.time() print('This page cost:',end2 - start2,'s') end = time.time() print('Total cost:',end - start,'s') def getLinks(self,number): #此函数可以获取给定numvber的页面中所有图片的链接,用List形式返回 url = ("https://alpha.wallhaven.cc/search?q={}&categories=111&purity=100&sorting=relevance&order=desc&page={}").format(keyWord,number) try: html = requests.get(url,headers = self.headers,proxies = self.proxies) selector = etree.HTML(html.text) pic_Linklist = selector.xpath('//a[@class="jsAnchor thumb-tags-toggle tagged"]/@href') except Exception as e: print(repr(e)) return pic_Linklist def download(self,url,count): #此函数用于图片下载。其中参数url是形如:https://alpha.wallhaven.cc/wallpaper/616442/thumbTags的网址 #616442是图片编号,我们需要用strip()得到此编号,然后构造html,html是图片的最终直接下载网址。 string = url.strip('/thumbTags').strip('https://alpha.wallhaven.cc/wallpaper/') html = 'http://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-' + string + '.jpg' pic_path = (self.filePath + keyWord + str(count) + '.jpg' ) try: start = time.time() pic = requests.get(html,headers = self.headers) f = open(pic_path,'wb') f.write(pic.content) f.close() end = time.time() print(f"Image:{count} has been downloaded,cost:",end - start,'s') except Exception as e: print(repr(e))spider = Spider()spider.main_fuction()
下载77张图片总耗时23.993554830551147 s
对比一下,77张图片的下载时间从157.17s变为23.99s,快了超过6倍。仅仅是简单的改造,多线程对比单线程的提升还是很明显的,其实还可以自己改写多线程算法,还可以加上多进程充分利用CPU数量,还可以用异步协程处理,总之,还有很多可以优化的空间~
Python——threading同时运行多个线程实例讲解 营销视频课程
Python里面经常会用到多线程,即所有的方法在同一时间开始运行,而不是按顺序一个一
个运行。所用到的模块为threading,下面详解threading用法。
一、我们写三个方法,one、two、three并正常运行。
这里只截图了one()方法,two、three与one内容一样。
按下面图中的运行方式,三个函数是分别在不同时间运行的。
这种方式三个函数时在不同时间运行的
二、我们用threading使三个方法在同一时间运行
定义一个线程池并把要运行的线程one()/two()/three()都写到这个线程池列表里:
threads = []#定义一个线程池
t1 = threading.Thread(target=one,args=(,))#建立一个线程并且赋给t1,这个线程指定调用方法one,并且不带参数
threads.append(t1)#把t1线程装到threads线程池里
t2 = threading.Thread(target=two)
threads.append(t2)
t3 = threading.Thread(target=three)
threads.append(t3)
这时threads这个列表中就有三个线程装在里面了。
下面就是运行这个线程池里面的线程
for t in threads:
用一个for语句遍历threads里的线程,然后调用start()方法运行
注意t.join()必须放在for语句外面。
三、运行结果为在同一时间启动的
结果每个循环都是在同一个时间运行
是不是很快就明白threading的用法了呢?
Python代码风格:PEP8规则 笔记 企业视频课程
Python程序设计的代码风格应该遵循PEP8规则:
一、代码布局
1、缩进:
每级缩进4个空格(不用Tab,更不空格Tab混用)
1、续行应该与其包裹元素对齐,要么使用圆括号、方括号和花括号内的隐式行连接来垂直对齐,要么使用悬挂式缩进对齐。当使用悬挂缩进时,应该考虑到第一行不应该有参数,以及使用缩进以区分自己是续行。
2、缩进4个空格的规则对于续行是可选的。
3、当 if 语句的条件部分长到需要换行写的时候,注意可以在两个字符关键字的连接处(比如 if ),增加一个空格,再增加一个左括号来创造一个4空格缩进的多行条件。这会与 if 语句内同样使用4空格缩进的代码产生视觉冲突。PEP没有明确指明要如何区分i发的条件代码和内嵌代码。可使用的选项包括但不限于下面几种情况:
4、(可以参考下面关于是否在二进制运算符之前或之后截断的讨论)
在多行结构中的大括号/中括号/小括号的右括号可以与内容对齐单独起一行作为最后一行的第一个字符,如:
或者也可以与多行结构的第一行第一个字符对齐,如:
2、Tab还是空格?
空格是被首先推荐的缩进方式。
Tab应该只在现有代码已经使用tab进行缩进的情况下使用,以便和现有代码保持一致。
Python 3不允许再同一个代码块中Tab和空格混合使用。
混合使用制表符和空格缩进的Python2代码应该统一转成空格。
使用命令行运行Python 2时,使用-t选项,会出现非法混用tab和空格的警告。当使用-tt选项时,这些警告会变成错误。强烈推荐使用这些选项!
3、最大行长
每行最大长度79个字符。
对于连续大段的文字(比如文档字符串(docstring)或注释),每行应该被限制在72个字符长度内。
Python标准库比较传统,将行长限制在79个字符以内(文档字符串/注释为72个字符)。
一种推荐的换行方式是利用Python圆括号、方括号和花括号中的隐式续行。长行可以通过在括号内换行来分成多行。应该最好加上反斜杠来区别续行。
有时续行只能使用反斜杠才。例如,较长的多个 with 语句不能采用隐式续行,只能接受反斜杠表示换行:
另一个这样的例子是assert语句。要确保续行的缩进适当。
在二元运算符之前应该换行吗?
遵循数学的传统能产出更多可读性高的代码:
4、空行
顶层函数和类的定义,前后用两个空行隔开。
类里的方法定义用一个空行隔开。
相关的功能组可以用额外的空行(尽量少地)隔开。一堆相关的单行代码之间的空白行可以省略(例如,一组虚拟实现 dummy implementations)。
在函数中使用空行来区分逻辑段(尽量少地)。
Python接受control-L(即^L)换页符作为空格;许多工具把这些字符当作页面分隔符,所以你可以在文件中使用它们来分隔相关段落。请注意,一些编辑器和基于Web的代码阅读器可能无法识别control-L为换页,将在其位置显示另一个字形。
5、源文件编码
Python核心发布版本中的代码总是以UTF-8格式编码(或者在Python2中用ASCII编码)。
使用ASCII(Python 2)或者UTF-8(Python 3)的文件不应该添加编码声明。
在标准库中,只有用作测试目的,或者注释或文档字符串需要提及作者名字而不得不使用非ASCII字符时,才能使用非默认的编码。否则,在字符串文字中包括非ASCII数据时,推荐使用\x, \u, U或N等转义符。
对于Python 3.0及其以后的版本中,标准库遵循以下原则(参见PEP 3131):Python标准库中的所有标识符都必须只采用ASCII编码的标识符,在可行的条件下也应当使用英文词(很多情况下,使用的缩写和技术术语词都不是英文)。此外,字符串文字和注释应该只包括ASCII编码。只有两种例外:
(a) 测试情况下为了测试非ASCII编码的特性
(b) 作者名字。作者名字不是由拉丁字母组成的也必须提供一个拉丁音译名。
鼓励面向全球的开源项目都采用类似的原则。
6、导入
1、imports应该分行写,而不是都写在一行,例如:
这样写也是可以的:
导入(import)始终在文件的顶部,在模块注释和文档字符串之后,在模块全局变量和常量之前。
导入顺序如下:
imports应该按照下面的顺序分组来写:
1、标准库imports
2、相关第三方imports
3、本地应用/库的特定imports
不同组的imports之前用空格隔开。
将任何相关的 __all__ 说明(specification)放在imports之后。
推荐使用绝对(absolute)imports,因为这样通常更易读,在import系统没有正确配置的情况下,也会有更好的表现(或者至少会给出错误信息):
在绝对路径比较长的情况下,也可以使用相对导入:
Python 3中已经禁止隐式的相对导入。
导入类的方法,通常可以这样写:
如果和本地命名的拼写产生了冲突,应当使用绝对导入:
禁止使用通配符导入。
通配符导入(from import *)应该避免,因为它不清楚命名空间有哪些名称存,混淆读者和许多自动化的工具。唯一的例外是重新发布对外的API时可以考虑使用。
7、模块中前后具有双下划线的变量名
像__all__ , __author__ , __version__ 等这样的模块中的变量名(也就是名字里有两个前缀下划线和两个后缀下划线),应该放在文档字符串的后面,以及除from __future__ 之外的import表达式前面。Python要求将来在模块中的导入,必须出现在除文档字符串之外的其他代码之前。
比如:
二、字符串引号
Python中单引号字符串和双引号字符串都是相同的。注意尽量避免在字符串中的反斜杠以提高可读性。
根据PEP 257, 三个引号都使用双引号。
三、表达式和语句中的空格
在下列情况下,避免使用无关的空格:
1、紧跟在小括号,中括号或者大括号后。
2、紧贴在逗号、分号或者冒号之前。
3、然而,冒号在切片中就像二元运算符,在两边应该有相同数量的空格(把它当做优先级最低的操作符)。在扩展的切片操作中,所有的冒号必须有相同的间距。例外情况:当一个切片参数被省略时,空格就被省略了。
4、紧贴在函数参数的左括号之前。
5、紧贴索引或者切片的左括号之前。
6、为了和另一个赋值语句对齐,在赋值运算符附件加多个空格。
其他建议
1、避免在尾部添加空格。因为尾部的空格通常都看不见,会产生混乱:比如,一个反斜杠后面跟一个空格的换行符,不算续行标记。有些编辑器不会保留尾空格,并且很多项目(像CPython)在pre-commit的挂钩调用中会过滤掉尾空格。
总是在二元运算符两边加一个空格:赋值(=),增量赋值(+=,-=),比较(==,,!=,,=,in,not,in,is,is not),布尔(and, or, not)。
如果使用具有不同优先级的运算符,请考虑在具有最低优先级的运算符周围添加空格。有时需要通过自己来判断;但是,不要使用一个以上的空格,并且在二元运算符的两边使用相同数量的空格。
2、在指定函数 关键字参数 或者 默认参数 值的时候,不要在=附近加上空格。
3、功能型注释应该使用冒号的一般性规则,并且在使用 ->的时候要在两边加空格。(参考下面的功能注释得到能够多信息)
4、当给有类型备注的参数赋值的时候,在=两边添加空格(仅针对那种有类型备注和默认值的参数)。
5、复合语句(同一行中的多个语句)通常是不允许的。
6、虽然有时候将小的代码块和 if/for/while 放在同一行没什么问题,多行语句块的情况不要这样用,同样也要避免代码行太长!
四、注释
与代码自相矛盾的注释比没注释更差。修改代码时要优先更新注释!
注释是完整的句子。如果注释是断句,首字母应该大写,除非它是小写字母开头的标识符(永远不要修改标识符的大小写)。
如果注释很短,可以省略末尾的句号。注释块通常由一个或多个段落组成。段落由完整的句子构成且每个句子应该以点号(后面要有两个空格)结束,并注意断词和空格。
非英语国家的程序员请用英语书写你的注释,除非你120%确信代码永远不会被不懂你的语言的人阅读。
1、注释块
注释块通常应用在代码前,并和这些代码有同样的缩进。每行以 '# '(除非它是注释内的缩进文本,注意#后面有空格)。
注释块内的段落用仅包含单个 '#' 的行分割。
2、行内注释
慎用行内注释(Inline Comments) 节俭使用行内注释。 行内注释是和语句在同一行,至少用两个空格和语句分开。行内注释不是必需的,重复罗嗦会使人分心。
不推荐:
但是有时,很有必要:
加了以后对理解代码很有帮助的情况下,关键处才加。
3、文档字符串
文档字符串的标准参见:PEP 257。
为所有公共模块、函数、类和方法书写文档字符串。非公开方法不一定有文档字符串,建议有注释(出现在 def 行之后)来描述这个方法做什么。
更多参考:PEP 257 文档字符串约定。注意结尾的 """ 应该单独成行,例如:
单行的文档字符串,结尾的 """ 在同一行。
4、版本标签
如果你必须在源文件中包含git、Subversion、CVS或RCS crud信息,放置在模块的文档字符串之后,任何其他代码之前,上下各用一个空行:
五、命名规范
Python库的命名约定有点混乱,不可能完全一致。但依然有些普遍推荐的命名规范的。新的模块和包 (包括第三方的框架) 应该遵循这些标准。对不同风格的已有的库,建议保持内部的一致性。
1、最重要的原则
用户可见的API命名应遵循使用约定而不是实现。
2、命名风格
以下是常见的命名方式:
b(单个小写字母)
B(单个大写字母)
lowercase (小写字母)
lower_case_with_underscores (使用下划线分隔的小写字母)
UPPERCASE( 大写字母)
UPPER_CASE_WITH_UNDERSCORES (使用下划线分隔的大写字母)
CapitalizedWords(首字母大写的单词串或驼峰缩写)
注意: 使用大写缩写时,缩写使用大写字母更好。故 HTTPServerError 比 HttpServerError 更好。
mixedCase(不同于首字母大写,第一个单词的首字母小写)
Capitalized_Words_With_Underscores(带下划线,首字母大写,巨丑无比)
还有一种风格使用短前缀分组名字。这在Python中不常用, 但出于完整性提一下。例如,os.stat()返回的元组有st_mode, st_size, st_mtime等等这样的名字(与POSIX系统调用结构体一致)。
X11库的所有公开函数以X开头, Python中通常认为是不必要的,因为属性和方法名有对象作前缀,而函数名有模块名为前缀。
下面讲述首尾有下划线的情况:
_single_leading_underscore:(单前置下划线): 弱内部使用标志。 例如"from M import " 不会导入以下划线开头的对象。
single_trailing_underscore_(单后置下划线): 用于避免与 Python关键词的冲突。 例如:
__double_leading_underscore(双前置下划线): 当用于命名类属性,会触发名字重整。 (在类FooBar中,__boo变成 _FooBar__boo)。
__double_leading_and_trailing_underscore__(双前后下划线):用户名字空间的魔法对象或属性。例如:__init__ , __import__ or __file__,不要自己发明这样的名字。
3、命名约定规范
避免采用的名字:
决不要用字符'l'(小写字母el),'O'(大写字母oh),或 'I'(大写字母eye) 作为单个字符的变量名。一些字体中,这些字符不能与数字1和0区别。用'L' 代替'l'时。
包和模块名:
模块名要简短,全部用小写字母,可使用下划线以提高可读性。包名和模块名类似,但不推荐使用下划线。
模块名对应到文件名,有些文件系统不区分大小写且截短长名字,在 Unix上不是问题,但当把代码迁移到 Mac、Windows 或 DOS 上时,就可能是个问题。当然随着系统的演进,这个问题已经不是经常出现。
另外有些模块底层用C或C++ 书写,并有对应的高层Python模块,C/C++模块名有一个前置下划线 (如:_socket)。
类名:
遵循CapWord。
接口需要文档化并且可以调用时,可能使用函数的命名规则。
注意大部分内置的名字是单个单词(或两个),CapWord只适用于异常名称和内置的常量。
异常名:
如果确实是错误,需要在类名添加后缀 "Error"。
全局变量名:
变量尽量只用于模块内部,约定类似函数。
对设计为通过 "from M import " 来使用的模块,应采用 __all__ 机制来防止导入全局变量;或者为全局变量加一个前置下划线。
函数名:
函数名应该为小写,必要时可用下划线分隔单词以增加可读性。 mixedCase(混合大小写)仅被允许用于兼容性考虑(如: threading.py)。
函数和方法的参数:
实例方法第一个参数是 'self'。
类方法第一个参数是 'cls'。
如果函数的参数名与保留关键字冲突,通常在参数名后加一个下划线。
方法名和实例变量:
同函数命名规则。
非公开方法和实例变量增加一个前置下划线。
为避免与子类命名冲突,采用两个前置下划线来触发重整。类Foo属性名为__a, 不能以 Foo.__a访问。(执著的用户还是可以通过Foo._Foo__a。) 通常双前置下划线仅被用来避免与基类的属性发生命名冲突。
常量:
<...Python——threading同时运行多个线程实例讲解 行业视频课程
Python里面经常会用到多线程,即所有的方法在同一时间开始运行,而不是按顺序一个一
个运行。所用到的模块为threading,下面详解threading用法。
一、我们写三个方法,one、two、three并正常运行。
这里只截图了one()方法,two、three与one内容一样。
按下面图中的运行方式,三个函数是分别在不同时间运行的。
这种方式三个函数时在不同时间运行的
二、我们用threading使三个方法在同一时间运行
定义一个线程池并把要运行的线程one()/two()/three()都写到这个线程池列表里:
threads = []#定义一个线程池
t1 = threading.Thread(target=one,args=(,))#建立一个线程并且赋给t1,这个线程指定调用方法one,并且不带参数
threads.append(t1)#把t1线程装到threads线程池里
t2 = threading.Thread(target=two)
threads.append(t2)
t3 = threading.Thread(target=three)
threads.append(t3)
这时threads这个列表中就有三个线程装在里面了。
下面就是运行这个线程池里面的线程
for t in threads:
用一个for语句遍历threads里的线程,然后调用start()方法运行
注意t.join()必须放在for语句外面。
三、运行结果为在同一时间启动的
结果每个循环都是在同一个时间运行
是不是很快就明白threading的用法了呢?