PythonSpot-中文系列教程-一-
PythonSpot 中文系列教程(一)
初学者
介绍
欢迎来到我的 Python 课程!
Python 是一种通用的计算机编程语言。
本课程适用于 Python 2 和 Python 3。
下载 Python
要运行 Python 代码,您将需要以下程序之一:
仅用于终端:Apple Mac OS X,Microsoft Windows,Linux/UNIX
</picture>
运行 Python 代码
python 程序应保存为扩展名为.py
的文件。试试这个代码:
print("Hello World!")
print("This is a Python program.")
预期产出:
Hello World!
This is a Python program
如果使用解释器,请使用:
python program.py
Python 字符串
字符串,一系列字符
字符串是一系列字符,它们通常用于显示文本。
要定义字符串,只需在引号之间输入文本。 Python 接受单引号,双引号和三引号。
字符串输入和输出
要将文本(字符串)输出到屏幕:
s = "hello world"
print(s)
要从键盘获取文本:
name = input("Enter name: ")
print(name)
如果您使用的是旧的 Python 版本(2.x),则需要使用:
name = raw_input("Enter name: ")
print(name)
要测试您的版本,请执行以下操作:
python –version
字符串比较
要测试两个字符串是否相等,请使用相等运算符(==
)。
#!/usr/bin/python
sentence = "The cat is brown"
q = "cat"
if q == sentence:
print('strings equal')
要测试两个字符串是否相等,请使用不等运算符(!=
)
#!/usr/bin/python
sentence = "The cat is brown"
q = "cat"
if q != sentence:
print('strings equal')
字符串(第 2 部分)
字符串是一系列字符,它们通常用于显示文本。
要定义字符串,只需在引号之间输入文本。 Python 接受单引号,双引号和三引号。
字符串索引
Python 为字符串的字符建立索引,每个索引都与一个唯一字符相关联。 例如,字符串"python"
中的字符具有索引:
字符串编号
字符串中的字符
第 0 个索引用于字符串的第一个字符。 请尝试以下操作:
#!/usr/bin/python
s = "Hello Python"
print(s) # prints whole string
print(s[0]) # prints "H"
print(s[1]) # prints "e"
字符串切片
给定字符串s
,切片的语法为:
s[ startIndex : pastIndex ]
startIndex
是字符串的起始索引。pastIndex
是切片末尾加 1。
如果省略第一个索引,则切片将从头开始。 如果省略最后一个索引,则切片将转到字符串的末尾。 例如:
#!/usr/bin/python
s = "Hello Python"
print(s[0:2]) # prints "He"
print(s[2:4]) # prints "ll"
print(s[6:]) # prints "Python"
Python 变量
Python 中的变量(x
,y
,z
)。它们可以稍后在程序中使用
变量可以保存您可以使用一次或多次的数字。
数字可以是以下数据类型之一:
-
整数(
1,2,3,4
) -
浮点(点后面的数字)
-
布尔值(真或假)
数值变量示例
数值变量示例:
x = 1
y = 1.234
z = True
您可以使用print()
函数将它们输出到屏幕上。
x = 1
y = 1.234
z = True
print(x)
print(y)
print(z)
Python 支持算术运算,例如加法(+
),乘法(*
),除法(/
)和减法(-
)。
#!/usr/bin/env python
x = 3
y = 8
sum = x + y
print(sum)
用户输入
Python 3
使用input()
函数获取文本输入,使用int()
或float()
转换为数字。
#!/usr/bin/env python
x = int(input("Enter x:"))
y = int(input("Enter y:"))
sum = x + y
print(sum)
Python 2 (旧版本)
您也可以使用raw_input
函数要求用户输入:
#!/usr/bin/env python
x = int(raw_input("Enter x:"))
y = int(raw_input("Enter y:"))
sum = x + y
print(sum)
Python 列表
列表是一个序列和一个基本的数据结构。 列表可以包含字符串(文本)和数字。 列表类似于其他编程语言中的数组,但具有其他功能。
Python 列表
我们用方括号[]
定义列表。 要访问数据,请使用这些相同的括号。列表用法示例:
#!/usr/bin/python
l = [ "Drake", "Derp", "Derek", "Dominique" ]
print(l) # prints all elements
print(l[0]) # print first element
print(l[1]) # prints second element
添加/删除
我们可以使用append()
和remove()
函数来操作列表。
#!/usr/bin/python
l = [ "Drake", "Derp", "Derek", "Dominique" ]
print(l) # prints all elements
l.append("Victoria") # add element.
print(l) # print all elements
l.remove("Derp") # remove element.
l.remove("Drake") # remove element.
print(l) # print all elements.
排序列表
我们可以使用sort()
函数对列表进行排序。
#!/usr/bin/python
l = [ "Drake", "Derp", "Derek", "Dominique" ]
print(l) # prints all elements
l.sort() # sorts the list in alphabetical order
print(l) # prints all elements
如果要按降序排列列表,只需使用reverse()
函数。
#!/usr/bin/python
l = [ "Drake", "Derp", "Derek", "Dominique" ]
print(l) # prints all elements
l.sort() # sorts the list in alphabetical order
l.reverse() # reverse order.
print(l) # prints all elements
if
语句
在 Python 中,您可以定义条件语句,称为if
语句。如果满足某些条件,则将执行代码块。
if
语句
考虑这个应用程序,它根据x
的值执行第一或第二个代码。
#!/usr/bin/python
x = 3
if x > 10:
print("x smaller than 10")
else:
print("x is bigger than 10 or equal")
如果将x
设置为大于 10,它将执行第二个代码块。 我们使用缩进(4 个空格)定义块。
一个小游戏:
用户可能并不总是定义变量,请考虑以下小游戏:
age = 24
print "Guess my age, you have 1 chances!"
guess = int(raw_input("Guess: "))
if guess != age:
print("Wrong!")
else:
print("Correct")
条件运算符
关于条件运算符
不要将赋值运算符(=
)与相等运算符(==
)混淆。
嵌套
执行多个条件的最直接的方法是嵌套:
运算符 | 说明 |
---|---|
!= |
不等 |
== |
等于 |
> |
大于 |
< |
小于 |
a = 12
b = 33
if a > 10:
if b > 20:
print("Good")
考虑结合 4 或 6 个条件,这可能很快变得难以阅读。 幸运的是,Python 有一个解决方案,我们可以使用and
关键字组合条件。
guess = 24
if guess > 10 and guess < 20:
print("In range")
else:
print("Out of range")
有时您可能想使用or
运算符。
函数
函数是可重用的代码,可以在程序中的任何位置调用。 函数提高了代码的可读性:使用函数而不是冗长的指令列表,使人们更容易理解代码。
最重要的是,可以重复使用或修改函数,这也提高了可测试性和可扩展性。
函数定义
我们使用以下语法来定义函数:
def function(parameters):
instructions
return value
def
关键字告诉 Python 我们有一段可重用的代码(一个函数)。 一个程序可以具有许多函数。
实际例子
我们可以使用function(parameters)
来调用函数。
#!/usr/bin/python
def f(x):
return(x*x)
print(f(3))
输出:
9
该函数具有一个参数x
。 返回值是函数返回的值。 并非所有函数都必须返回某些内容。
参数
您可以传递多个变量:
#!/usr/bin/python
def f(x,y):
print('You called f(x,y) with the value x = ' + str(x) + ' and y = ' + str(y))
print('x * y = ' + str(x*y))
f(3,2)
输出:
You called f(x,y) with the value x = 3 and y = 2
x * y = 6
全局和局部变量
变量有两种类型:全局变量和局部变量。全局变量可以在代码中的任何位置访问,局部变量只能在作用域中访问。
可以在代码中的任何位置访问和修改全局变量(x
),局部变量(z
)仅存在于块 3 中。
局部变量
局部变量只能在其作用域内达到。下面的示例有两个局部变量:x
和y
。
def sum(x,y):
sum = x + y
return sum
print(sum(8,6))
变量x
和y
只能在函数sum
之内使用,而在函数外部则不存在。局部变量不能在其作用域之外使用,此行将不起作用:
print(x)
全局变量
全局变量可以在代码中的任何位置使用。在下面的示例中,我们定义了全局变量z
z = 10
def afunction():
global z
print(z)
afunction()
print(z)
全局变量z
可以在整个程序中,函数内部或外部使用。可以在函数内部修改全局变量,并为整个程序进行更改:
z = 10
def afunction():
global z
z = 9
afunction()
print(z)
调用afunction()
之后,将更改整个程序的全局变量。
练习
局部变量和全局变量可以在同一程序中一起使用。尝试确定该程序的输出:
z = 10
def func1():
global z
z = 3
def func2(x,y):
global z
return x+y+z
func1()
total = func2(4,5)
print(total)
作用域
作用域
变量只能到达定义它们的区域,这称为作用域。 将其视为可以使用变量的代码区域。 Python 支持全局变量(可在整个程序中使用)和局部变量。
默认情况下,函数中声明的所有变量都是局部变量。要访问函数内部的全局变量,必须明确定义“全局变量”。
示例
下面我们将研究局部变量和作用域的用法。它不起作用:
#!/usr/bin/python
def f(x,y):
print('You called f(x,y) with the value x = ' + str(x) + ' and y = ' + str(y))
print('x * y = ' + str(x*y))
z = 4 # cannot reach z, so THIS WON'T WORK
z = 3
f(3,2)
但这将:
#!/usr/bin/python
def f(x,y):
z = 3
print('You called f(x,y) with the value x = ' + str(x) + ' and y = ' + str(y))
print('x * y = ' + str(x*y))
print(z) # can reach because variable z is defined in the function
f(3,2)
让我们进一步研究一下:
#!/usr/bin/python
def f(x,y,z):
return x+y+z # this will return the sum because all variables are passed as parameters
sum = f(3,2,1)
print(sum)
调用函数
中的函数我们还可以从另一个函数中获取变量的内容:
#!/usr/bin/python
def highFive():
return 5
def f(x,y):
z = highFive() # we get the variable contents from highFive()
return x+y+z # returns x+y+z. z is reachable becaue it is defined above
result = f(3,2)
print(result)
如果在代码中的任何位置都可以访问变量,则称为全局变量。如果仅在作用域内部知道变量,则将其称为局部变量。
循环:For
循环,while
循环
可以使用循环来重复代码。 代码行可以重复 N 次,其中 N 是可以手动配置的。 实际上,这意味着将重复执行代码,直到满足条件为止。 此条件通常为(x <= N
),但这不是唯一可能的条件。
Python 有 3 种循环类型:for
循环,while
循环和嵌套循环。
for
循环
我们可以使用for
循环迭代列表
#!/usr/bin/python
items = [ "Abby","Brenda","Cindy","Diddy" ]
for item in items:
print(item)
for
循环的可视化:
for
循环也可以重复 N 次:
#!/usr/bin/python
for i in range(1,10):
print(i)
While
循环
如果不确定代码应重复多少次,请使用while
循环。例如,
correctNumber = 5
guess = 0
while guess != correctNumber:
guess = int(input("Guess the number: "))
if guess != correctNumber:
print('False guess')
print('You guessed the correct number')
嵌套循环
我们可以使用嵌套组合for
循环。 如果我们要遍历(x, y)
字段,可以使用:
#!/usr/bin/python
for x in range(1,10):
for y in range(1,10):
print("(" + str(x) + "," + str(y) + ")")
嵌套非常有用,但是嵌套得越深,它就会增加复杂性。
Python 范围
range()
函数会生成一个数字序列,从下限到上限。
range(lower_bound, upper_bound, step_size)
-
lower_bound
:列表的起始值。 -
upper_bound
:列表的最大值,不包括此数字。 -
step_bound
:步长,列表中每个数字之间的差。
lower_bound
和step_size
参数是可选的。默认情况下,下限设置为零,增量步长设置为一。参数必须为整数类型,但可以为负。
解释器中的 python range
函数
范围实现差异
通常是一个问题。 在 Python 版本中,range()
的实现略有不同:
-
Python 2.x:
range()
函数返回一个列表。 -
Python 3.x:
range()
函数生成一个序列。
python 2.7 中的范围
调用range(5)
将返回:0, 1, 2, 3, 4
。
>>> range(5)
调用range(1, 10)
返回:1,2,3,4,5,6,7,8,9
>>> range(1,10)
调用range(0, 10, 2)
返回:0,2,4,6,8
>>> range(0,10,2)
python 3 中的范围。要使用范围生成列表,请添加列表函数。
>>> list(range(5))
我们可以使用所有参数(下限,上限,步长)
>>> list(range(0,10,2))
[0, 2, 4, 6, 8]
python 2 实现
此版本的range()
分配计算机内存,并在后台填充计算机内存。 对于大范围,这不是很有效的实现。
通常,range
的 Python2 实现不会有任何问题,但如果使用大量(数百万个项目),则可能会遇到问题。
Python 元组
元组数据结构用于存储一组数据。 该组中的元素用逗号分隔。 创建后,元组的值将无法更改。
Python 元组
Python 中的空元组将定义为:
tuple = ()
具有一个项目的元组需要逗号:
tuple = (3,)
一项的逗号可能很直观,但是如果没有一项的逗号,则无法访问该元素。 对于多个项目,您不必在末尾加逗号。 此集是一个示例:
personInfo = ("Diana", 32, "New York")
元组中的数据可以是一种或多种数据类型,例如文本和数字。
数据存取
要访问数据,我们可以简单地使用索引。 通常,索引是括号之间的数字:
#!/usr/bin/env python
personInfo = ("Diana", 32, "New York")
print(personInfo[0])
print(personInfo[1])
如果要一次分配多个变量,则可以使用元组:
#!/usr/bin/env python
name,age,country,career = ('Diana',32,'Canada','CompSci')
print(country)
在右侧记录了元组。 等于运算符的左侧是对应的输出变量。
附加到 Python 中的元组
如果您有一个现有的元组,则可以使用+
运算符将其追加。 您只能将元组追加到现有元组。
#!/usr/bin/env python
x = (3,4,5,6)
x = x + (1,2,3)
print(x)
Python 字典
字典可以看作是键值对的无序集合。
一对大括号创建一个空字典: {}
。 每个元素都可以映射到某个值。 整数或字符串可用于索引。 字典没有命令。
字典示例
让我们生成一个简单的字典:
#!/usr/bin/python
words = {}
words["Hello"] = "Bonjour"
words["Yes"] = "Oui"
words["No"] = "Non"
words["Bye"] = "Au Revoir"
print(words["Hello"])
print(words["No"])
输出:
Bonjour
Non
我们绝不限于值部分中的单个单词定义。 演示:
#!/usr/bin/python
dict = {}
dict['Ford'] = "Car"
dict['Python'] = "The Python Programming Language"
dict[2] = "This sentence is stored here."
print(dict['Ford'])
print(dict['Python'])
print(dict[2])
输出:
Car
The Python Programming Language
This sentence is stored here.
使用字典
声明后,我们可以操作存储在字典中的数据。 在下面的示例中显示:
#!/usr/bin/python
words = {}
words["Hello"] = "Bonjour"
words["Yes"] = "Oui"
words["No"] = "Non"
words["Bye"] = "Au Revoir"
print(words) # print key-pairs.
del words["Yes"] # delete a key-pair.
print(words) # print key-pairs.
words["Yes"] = "Oui!" # add new key-pair.
print(words) # print key-pairs.
输出:
{'Yes': 'Oui', 'Bye': 'Au Revoir', 'Hello': 'Bonjour', 'No': 'Non'}
{'Bye': 'Au Revoir', 'Hello': 'Bonjour', 'No': 'Non'}
{'Yes': 'Oui!', 'Bye': 'Au Revoir', 'Hello': 'Bonjour', 'No': 'Non'}
数据类型转换
Python 自动确定数据类型,以说明:
x = 3
y = "text"
它发现x
是整数类型,y
是字符串类型。
函数接受某种数据类型。 例如,print
仅接受字符串数据类型。
数据类型转换
如果要打印数字,则经常需要强制转换。
在下面的示例中,我们要打印两个数字,一个整数(整数)和一个浮点数。
x = 3
y = 2.15315315313532
print("We have defined two numbers,")
print("x = " + str(x))
print("y = " + str(y))
我们使用str()
函数将变量x
(整数)和变量y
(浮点数)转换为字符串。
如果我们有要存储为数字的文本怎么办? 我们将不得不再次转型。
a = "135.31421"
b = "133.1112223"
c = float(a) + float(b)
print(c)
在上面的示例中,我们将两个具有数据类型字符串的变量强制转换为数据类型float
。
转换函数
要在数据类型之间转换,可以使用:
函数 | 描述 |
---|---|
int(x) |
将x 转换为整数 |
long(x) |
将x 转换为长整数 |
float(x) |
将x 转换为浮点数 |
str(x) |
将x 转换为字符串。x 可以是float 类型。 整数或长整数。 |
hex(x) |
将x 整数转换为十六进制字符串 |
asc(x) |
将x 整数转换为字符 |
ord(x) |
将字符x 转换为整数 |
随机数
使用random
模块,我们可以生成伪随机数。 函数random()
生成一个介于零和一之间的随机数[0, 0.1 .. 1]
。 用此模块生成的数字不是真正随机的,但对于大多数用途而言,它们是足够随机的。
介于 0 和 1 之间的随机数。
我们可以使用以下小代码生成(伪)随机浮点数:
from random import *
print(random()) # Generate a pseudo-random number between 0 and 1.
生成一个 1 到 100 之间的随机数
要生成一个介于一百到一百之间的整数(整数),请使用:
from random import *
print(randint(1, 100)) # Pick a random number between 1 and 100.
这将打印一个随机整数。 如果要将其存储在变量中,可以使用:
from random import *
x = randint(1, 100) # Pick a random number between 1 and 100.
print(x)
1 到 10 之间的随机数
要生成 1 到 10 之间的随机浮点数,您可以使用uniform()
函数
from random import *
print(uniform(1, 10))
从列表中选择一个随机项目
打乱列表
我们可以使用以下代码对列表进行随机排列:
from random import *
items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
shuffle(items)
print(items)
要从列表中选择一个随机数:
from random import *
items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x = sample(items, 1) # Pick a random item from the list
print(x[0])
y = sample(items, 4) # Pick 4 random items from the list
print(y)
我们可以使用字符串列表来做同样的事情:
from random import *
items = ['Alissa','Alice','Marco','Melissa','Sandra','Steve']
x = sample(items, 1) # Pick a random item from the list
print(x[0])
y = sample(items, 4) # Pick 4 random items from the list
print(y)
数据和数据库
读取文件
您之前已经看过各种类型的数据持有者:整数,字符串,列表。 但是到目前为止,我们还没有讨论如何读取或写入文件。
读取文件
您可以使用以下代码读取文件。
该文件必须与程序位于同一目录中,如果不是,则需要指定路径。
#!/usr/bin/env python
# Define a filename.
filename = "bestand.py"
# Open the file as f.
# The function readlines() reads the file.
with open(filename) as f:
content = f.readlines()
# Show the file contents line by line.
# We added the comma to print single newlines and not double newlines.
# This is because the lines contain the newline character '\n'.
for line in content:
print(line),
代码的第一部分将读取文件内容。 读取的所有行将存储在变量内容中。 第二部分将遍历变量内容中的每一行。
如果您不想读取换行符"\n"
,则可以将语句f.readlines()
更改为此:
content = f.read().splitlines()
产生此代码:
#!/usr/bin/env python
# Define a filename.
filename = "bestand.py"
# Open the file as f.
# The function readlines() reads the file.
with open(filename) as f:
content = f.read().splitlines()
# Show the file contents line by line.
# We added the comma to print single newlines and not double newlines.
# This is because the lines contain the newline character '\n'.
for line in content:
print(line)
当上面的代码起作用时,我们应该始终测试要打开的文件是否存在。 我们将首先测试文件是否不存在,如果存在,它将读取文件,否则返回错误。 如下面的代码:
#!/usr/bin/env python
import os.path
# Define a filename.
filename = "bestand.py"
if not os.path.isfile(filename):
print('File does not exist.')
else:
# Open the file as f.
# The function readlines() reads the file.
with open(filename) as f:
content = f.read().splitlines()
# Show the file contents line by line.
# We added the comma to print single newlines and not double newlines.
# This is because the lines contain the newline character '\n'.
for line in content:
print(line)
写入文件
Python 默认支持写文件,不需要特殊模块。 您可以使用.write()
方法以及包含文本数据的参数来写入文件。
在将数据写入文件之前,请调用open(filename, 'w')
函数,其中filename
包含文件名或文件名的路径。 最后,别忘了关闭文件。
创建要写入的文件
下面的代码使用数据创建一个新文件(或覆盖)。
#!/usr/bin/env python
# Filename to write
filename = "newfile.txt"
# Open the file with writing permission
myfile = open(filename, 'w')
# Write a line to the file
myfile.write('Written with Python\n')
# Close the file
myfile.close()
"w"
标志可使 Python 截断该文件(如果已存在)。 也就是说,如果文件内容存在,它将被替换。
附加到文件
如果您只想向文件添加内容,则可以使用"a"
参数。
#!/usr/bin/env python
# Filename to append
filename = "newfile.txt"
# The 'a' flag tells Python to keep the file contents
# and append (add line) at the end of the file.
myfile = open(filename, 'a')
# Add the line
myfile.write('Written with Python\n')
# Close the file
myfile.close()
参数
参数总结:
标志 | 行为 |
---|---|
r |
打开文件以供读取 |
w |
打开文件进行写入(将截断文件) |
b |
二进制更多 |
r+ |
打开文件进行读写 |
a+ |
打开文件进行读写(附加到结尾) |
w+ |
打开文件进行读写(截断文件) |
Python 类:对象和类
介绍
技术总是在发展。什么是类,它们从何而来?
1. 语句:在计算的早期,程序员仅编写命令。
2. 函数:可重用的语句组,有助于结构化代码并提高了可读性。
3. 类:这些类用于创建具有功能和变量的对象。 字符串是对象的示例:字符串书具有功能book.replace()
和book.lowercase()
。这种样式通常称为面向对象编程。
让我们一起深入吧!
Python 类
我们可以在 Python 中创建虚拟对象。 虚拟对象可以包含变量和方法。 程序可能具有许多不同的类型,并且是从类创建的。 例:
class User:
name = ""
def __init__(self, name):
self.name = name
def sayHello(self):
print("Hello, my name is " + self.name)
# create virtual objects
james = User("James")
david = User("David")
eric = User("Eric")
# call methods owned by virtual objects
james.sayHello()
david.sayHello()
运行该程序。 在此代码中,我们有 3 个虚拟对象:james
,david
和eric
。 每个对象都是User
类的实例。
Python 类:创建对象
在此类中,我们定义了sayHello()
方法,这就是为什么我们可以为每个对象调用它的原因。__init__()
方法被称为构造函数,并且在创建对象时始终被调用。该类拥有的变量在这种情况下为name
。这些变量有时称为类属性。
我们可以在类中创建方法来更新对象的内部变量。这听起来可能有些含糊,但我将举一个例子进行说明。
类变量
我们定义了一个CoffeeMachine
类,其中的虚拟对象包含大量的咖啡豆和大量的水。 两者都定义为数字(整数)。然后我们可以定义添加或删除豆子的方法。
def addBean(self):
self.bean = self.bean + 1
def removeBean(self):
self.bean = self.bean - 1
对于水,我们也是如此。如下所示:
class CoffeeMachine:
name = ""
beans = 0
water = 0
def __init__(self, name, beans, water):
self.name = name
self.beans = beans
self.water = water
def addBean(self):
self.beans = self.beans + 1
def removeBean(self):
self.beans = self.beans - 1
def addWater(self):
self.water = self.water + 1
def removeWater(self):
self.water = self.water - 1
def printState(self):
print "Name = " + self.name
print "Beans = " + str(self.beans)
print "Water = " + str(self.water)
pythonBean = CoffeeMachine("Python Bean", 83, 20)
pythonBean.printState()
print ""
pythonBean.addBean()
pythonBean.printState()
运行该程序。 代码的顶部定义了我们所描述的类。 下面的代码是我们创建虚拟对象的地方。 在此示例中,我们只有一个对象称为pythonBean
。 然后我们调用更改内部变量的方法,这是可能的,因为我们在类中定义了这些方法。 输出:
Name = Python Bean
Beans = 83
Water = 20
Name = Python Bean
Beans = 84
Water = 20
Python 类
Python 中的所有内容都是一个对象。 每个对象都可以包含方法和变量(具有唯一值)。 对象是从类创建(通常称为实例化)的。
类示例
考虑以下示例:
class Animal:
def __init__(self,name):
self.name = name
def walk(self):
print(self.name + ' walks.')
duck = Animal('Duck')
duck.walk()
我们在动物类中创建了一个名为duck
的对象。 该类具有一个可以在每个对象上调用的方法(walk
)。 我们还有一个称为__init__()
的方法,该方法在创建新对象时总是被调用。 每种方法都必须使用self
关键字。 我们使用类(self.name = ..
)设置变量。
使用建模语言 UML 绘制的 Python 类和对象
创建对象后,我们可以调用其方法并无限期使用其变量。 同一类的每个对象都具有相同的方法,但是其变量内容可能有所不同。
Python 程序可能包含许多类和对象。 为了证明这一点,我们从一个类创建两个对象:
class Animal:
def __init__(self,name):
self.name = name
def walk(self):
print(self.name + ' walks.')
duck = Animal('Duck')
duck.walk()
rhino = Animal('African Rhino')
rhino.walk()
封装
在面向对象的 python 程序中,您可以限制对方法和变量的访问。这可以防止意外修改数据,这就是封装。 让我们从一个例子开始。
私有方法
封装。限制访问方法或变量
我们创建了一个Car
类,它具有两种方法:drive()
和updateSoftware()
。创建汽车对象时,它将调用私有方法__updateSoftware()
。
仅在类内部不能直接在对象上调用此函数。
#!/usr/bin/env python
class Car:
def __init__(self):
self.__updateSoftware()
def drive(self):
print('driving')
def __updateSoftware(self):
print('updating software')
redcar = Car()
redcar.drive()
#redcar.__updateSoftware() not accesible from object.
该程序将输出:
updating software
driving
封装可以防止意外访问,但不是有意访问。
私有属性和方法并未真正隐藏,而是在其名称的开头加上了_Car
来重命名。
实际上可以使用redcar._Car__updateSoftware()
调用该方法。
私有变量
具有私有变量的类
变量可以是私有的,这在许多情况下都可以使用。 私有变量只能在类方法内更改,而不能在类外部更改。
对象可以为您的应用程序保存关键数据,并且您不希望这些数据在代码中的任何位置都可以更改。
示例:
#!/usr/bin/env python
class Car:
__maxspeed = 0
__name = ""
def __init__(self):
self.__maxspeed = 200
self.__name = "Supercar"
def drive(self):
print('driving. maxspeed ' + str(self.__maxspeed))
redcar = Car()
redcar.drive()
redcar.__maxspeed = 10 # will not change variable because its private
redcar.drive()
如果要更改私有变量的值,则使用 setter 方法。 这只是设置私有变量值的一种方法。
#!/usr/bin/env python
class Car:
__maxspeed = 0
__name = ""
def __init__(self):
self.__maxspeed = 200
self.__name = "Supercar"
def drive(self):
print('driving. maxspeed ' + str(self.__maxspeed))
def setMaxSpeed(self,speed):
self.__maxspeed = speed
redcar = Car()
redcar.drive()
redcar.setMaxSpeed(320)
redcar.drive()
为什么要创建它们? 因为某些私有值可能需要在创建对象后更改,而其他私有值可能根本不需要更改。
Python 封装
总而言之,在 Python 中有:
其他编程语言也具有受保护的类方法,而 Python 没有。
封装使您可以更好地控制代码中的耦合程度,它允许类在不影响代码其他部分的情况下更改其实现。
类型 | 描述 |
---|---|
公共方法 | 可从任何地方访问 |
私有方法 | 仅在自己的课程中可访问。 以两个下划线开头 |
公共变量 | 可从任何地方访问 |
私有变量 | 仅在自己的类或方法(如果已定义)中可访问。 以两个下划线开头 |
方法重载
几种调用方法的方法(方法重载)
在 Python 中,您可以以一种多种方式来调用它来定义方法。
给定单个方法或函数,我们可以自行指定参数数量。
根据函数定义,可以使用零个,一个,两个或多个参数来调用它。
这称为方法重载。并非所有的编程语言都支持方法重载,但是 Python 支持。
方法重载示例
我们使用一个方法sayHello()
创建一个类。此方法的第一个参数设置为None
,这使我们可以选择是否使用参数来调用它。
一个基于该类创建的对象,我们使用零和一个参数调用其方法。
#!/usr/bin/env python
class Human:
def sayHello(self, name=None):
if name is not None:
print('Hello ' + name)
else:
print('Hello ')
# Create instance
obj = Human()
# Call the method
obj.sayHello()
# Call the method with a parameter
obj.sayHello('Guido')
输出:
Hello
Hello Guido
为了澄清方法的重载,我们现在可以通过两种方式调用sayHello()
方法:
obj.sayHello()
obj.sayHello('Guido')
我们创建了一个方法,该方法可以使用比定义所允许的参数更少的参数进行调用。
我们不仅限于两个变量,您的方法可以有更多可选的变量。
继承
类可以继承其他类的功能。 如果使用从超类继承的类创建对象,则该对象将包含该类和超类的方法。 对于超类和从超类继承的类的变量也是如此。
与其他流行的编程语言不同,Python 支持从多个类继承。
介绍
我们定义一个名为User
的基本类:
class User:
name = ""
def __init__(self, name):
self.name = name
def printName(self):
print("Name = " + self.name)
brian = User("brian")
brian.printName()
这将创建一个称为 brian 的实例,并输出其给定名称。 我们创建另一个称为 Programmer 的类。
class Programmer(User):
def __init__(self, name):
self.name = name
def doPython(self):
print("Programming Python")
除了参数中提供了User
之外,这看起来非常像标准类。 这意味着可以在Programmer
类中访问User
类的所有功能。
继承示例
Python 继承的完整示例:
class User:
name = ""
def __init__(self, name):
self.name = name
def printName(self):
print("Name = " + self.name)
class Programmer(User):
def __init__(self, name):
self.name = name
def doPython(self):
print("Programming Python")
brian = User("brian")
brian.printName()
diana = Programmer("Diana")
diana.printName()
diana.doPython()
输出:
Name = brian
Name = Diana
Programming Python
Brian
是User
的实例,只能访问方法printName
。Diana
是Programmer
的一个实例,该类是继承自User
的类,并且可以访问Programmer
和User
中的方法。
多态
有时,对象有多种类型或形式。 如果我们有一个按钮,则有许多不同的绘制输出(圆形按钮,复选按钮,方形按钮,带有图像的按钮),但它们确实共享相同的逻辑:onClick()
。 我们使用相同的方法访问它们。 这个想法称为多态。
多态是基于希腊语 Poly(许多)和 morphism(形式)。 我们将创建一个可以采用或使用多种形式的对象的结构。
具有函数的多态:
我们创建了两个类别:Bear
和Dog
,两者都能发出不同的声音。 然后,我们创建两个实例,并使用相同的方法调用它们的动作。
class Bear(object):
def sound(self):
print("Groarrr")
class Dog(object):
def sound(self):
print("Woof woof!")
def makeSound(animalType):
animalType.sound()
bearObj = Bear()
dogObj = Dog()
makeSound(bearObj)
makeSound(dogObj)
输出:
Groarrr
Woof woof!
抽象类的多态(最常用)
多态可视化。
抽象结构在Document
类中定义。
如果您创建编辑器,则可能事先不知道用户将打开哪种类型的文档(pdf 格式还是 word 格式?)。
像这样处理它们,而不是每个文档有 20 种类型,这不是很好吗?
for document in documents:
print document.name + ': ' + document.show()
为此,我们创建了一个称为document
的抽象类。 此类没有任何实现,但是定义了所有形式都必须具有的结构(以函数形式)。 如果我们定义函数show()
,则PdfDocument
和WordDocument
都必须具有show()
函数。完整代码:
class Document:
def __init__(self, name):
self.name = name
def show(self):
raise NotImplementedError("Subclass must implement abstract method")
class Pdf(Document):
def show(self):
return 'Show pdf contents!'
class Word(Document):
def show(self):
return 'Show word contents!'
documents = [Pdf('Document1'),
Pdf('Document2'),
Word('Document3')]
for document in documents:
print document.name + ': ' + document.show()
输出:
Document1: Show pdf contents!
Document2: Show pdf contents!
Document3: Show word contents!
我们有一个抽象访问点(文档),用于访问遵循相同结构的多种类型的对象(pdf,word)。
多态示例
抽象类中的结构,其他类中的实现
另一个例子是拥有一个抽象类Car
,其中包含了drive()
和stop()
结构。
我们定义了两个对象Sportcar
和Truck
,它们都是Car
的一种形式。 用伪代码我们将要做的是:
class Car:
def drive abstract, no implementation.
def stop abstract, no implementation.
class Sportscar(Car):
def drive: implementation of sportscar
def stop: implementation of sportscar
class Truck(Car):
def drive: implementation of truck
def stop: implementation of truck
然后,我们可以访问任何类型的汽车并调用函数,而无需进一步考虑表格是 Sportscar 还是 Truck。 完整代码:
class Car:
def __init__(self, name):
self.name = name
def drive(self):
raise NotImplementedError("Subclass must implement abstract method")
def stop(self):
raise NotImplementedError("Subclass must implement abstract method")
class Sportscar(Car):
def drive(self):
return 'Sportscar driving!'
def stop(self):
return 'Sportscar braking!'
class Truck(Car):
def drive(self):
return 'Truck driving slowly because heavily loaded.'
def stop(self):
return 'Truck braking!'
cars = [Truck('Bananatruck'),
Truck('Orangetruck'),
Sportscar('Z3')]
for car in cars:
print car.name + ': ' + car.drive()
输出:
Bananatruck: Truck driving slowly because heavily loaded.
Orangetruck: Truck driving slowly because heavily loaded.
Z3: Sportscar driving!
内部类
内部类或嵌套类完全是在另一个类的主体内定义的。 如果使用类创建对象,则可以使用根类内的对象。 一个类可以具有多个内部类,但是通常避免使用内部类。
内部类的例子
我们创建一个具有一个内部类(Head
)的类(Human
)。创建一个实例,该实例调用内部类中的方法:
#!/usr/bin/env python
class Human:
def __init__(self):
self.name = 'Guido'
self.head = self.Head()
class Head:
def talk(self):
return 'talking...'
if __name__ == '__main__':
guido = Human()
print guido.name
print guido.head.talk()
输出:
Guido
talking...
在上面的程序中,我们有内部类Head()
,它具有自己的方法。内部类可以同时具有方法和变量。在此示例中,类Human
的构造函数(__init__
)创建了一个新的head
对象。
多个内部类
您绝不限于内部类的数量,例如,以下代码也可以使用:
#!/usr/bin/env python
class Human:
def __init__(self):
self.name = 'Guido'
self.head = self.Head()
self.brain = self.Brain()
class Head:
def talk(self):
return 'talking...'
class Brain:
def think(self):
return 'thinking...'
if __name__ == '__main__':
guido = Human()
print(guido.name)
print(guido.head.talk())
print(guido.brain.think())
通过使用内部类,您可以使代码更加面向对象。 一个对象可以容纳多个子对象。 我们可以使用它们为程序添加更多结构。
工厂方法
我们可能并不总是知道我们要预先创建什么样的对象。
在用户请求执行后,只在执行时创建某些对象。
可能使用工厂方法的示例:
-
用户可以单击创建对象的特定按钮。
-
用户可以创建几个不同类型的新文档。
-
如果用户启动 Web 浏览器,则浏览器不会事先知道将打开多少个选项卡(每个选项卡都是一个对象)。
工厂方法模式
为了解决这个问题,我们可以使用工厂方法模式。这个想法是要有一个函数,即工厂,该函数接受一个输入字符串并输出一个对象。
obj = Car.factory("Racecar")
obj.drive()
关键事实:工厂方法返回(新)对象。
对象的类型取决于您指定的输入字符串的类型。 这种技术还可以使您的程序更容易扩展。 新的程序员可以通过添加新的字符串和类来轻松添加功能,而无需阅读所有源代码。
工厂方法示例
下面的示例演示了工厂方法。工厂方法(命名为factory
)将根据输入返回这两种类型的新对象。
class Car(object):
def factory(type):
if type == "Racecar":
return Racecar()
if type == "Van":
return Van()
factory = staticmethod(factory)
class Racecar(Car):
def drive(self):
print("Racecar driving.")
class Van(Car):
def drive(self):
print("Van driving.")
# Create object using factory.
obj = Car.factory("Racecar")
obj.drive()
输出:
Racecar driving.
递归
在英语中,有许多递归示例:
- “要了解递归,您必须先了解递归”,
- “人就是人的母亲”。
您可能想知道,这与编程有什么关系?
您可能需要将一个复杂的问题分解为几个较小的问题。 您已经熟悉循环或迭代。 在某些情况下,递归可能是更好的解决方案。
在 Python 中,如果函数调用自身并且具有终止条件,则该函数是递归的。 为什么要终止条件? 阻止函数无限自我调用。
递归示例
列表中的递归
让我们从一个非常基本的示例开始:将所有数字添加到列表中。 如果没有递归,则可能是:
#!/usr/bin/env python
def sum(list):
sum = 0
# Add every number in the list.
for i in range(0, len(list)):
sum = sum + list[i]
# Return the sum.
return sum
print(sum([5,7,3,8,10]))
在我们简单地调用sum
函数的地方,该函数将每个元素添加到变量sum
并返回。 递归执行此操作:
#!/usr/bin/env python
def sum(list):
if len(list) == 1:
return list[0]
else:
return list[0] + sum(list[1:])
print(sum([5,7,3,8,10]))
如果列表的长度为 1,则返回列表(终止条件)。 否则,它返回元素,并调用函数sum()
减去列表中的一个元素。 如果执行了所有调用,则返回达到终止条件并返回应答。
递归阶乘
阶乘的数学定义是:n! = n * (n-1)!
,如果n > 1
并且f(1) = 1
。示例:3! = 3 x 2 x 1 = 6
。我们可以使用递归函数在 Python 中实现:
#!/usr/bin/env python
def factorial(n):
if n == 1:
return 1
else:
return n * factorial(n-1)
print(factorial(3))
调用阶乘函数n = 3
时。它将返回n * factorial(n-1)
。 该过程将一直持续到n = 1
。如果达到n == 1
,它将返回结果。
递归限制
每次函数调用自身并存储一些内存。 因此,与传统函数相比,递归函数可以容纳更多的内存。 Python 在 1000 次调用的深度后停止函数调用。 如果运行此示例:
#!/usr/bin/env python
def factorial(n):
if n == 1:
return 1
else:
return n * factorial(n-1)
print(factorial(3000))
您将收到错误:
RuntimeError: maximum recursion depth exceeded
在其他编程语言中,您的程序可能会崩溃。 您可以通过修改递归调用的数量来解决此问题,例如:
#!/usr/bin/env python
import sys
sys.setrecursionlimit(5000)
def factorial(n):
if n == 1:
return 1
else:
return n * factorial(n-1)
print(factorial(3000))
但是请记住,阶乘函数的输入仍然有限制。 因此,您应该明智地使用递归。 正如您现在对阶乘问题所了解的那样,递归函数并不是最佳解决方案。 对于其他问题(例如遍历目录),递归可能是一个很好的解决方案。
日志
Python 日志记录
我们可以在软件应用程序中跟踪事件,这称为“日志”。让我们从一个简单的示例开始,我们将记录一条警告消息。
与仅打印错误相反,可以将日志记录配置为禁用输出或保存到文件。 这是简单打印错误的一大优势。
日志示例
import logging
# print a log message to the console.
logging.warning('This is a warning!')
这将输出:
WARNING:root:This is a warning!
我们可以轻松地输出到文件:
import logging
logging.basicConfig(filename='program.log',level=logging.DEBUG)
logging.warning('An example message.')
logging.warning('Another message')
日志消息的重要性取决于严重性。
严重程度
日志模块具有多个严重级别。我们使用以下代码行设置严重性级别:
logging.basicConfig(level=logging.DEBUG)
这些是严重性级别:
默认的日志记录级别是警告,表示其他消息将被忽略。 如果要打印调试或信息日志消息,则必须更改日志记录级别,如下所示:
类型 | 描述 |
---|---|
DEBUG |
仅用于问题诊断的信息 |
INFO |
该程序正在按预期运行 |
WARNING |
指示出了问题 |
ERROR |
该软件将不再能够运行 |
CRITICAL |
非常严重的错误 |
import logging
logging.basicConfig(level=logging.DEBUG)
logging.debug('Debug message')
记录时间
您可以使用以下代码行启用日志记录时间:
logging.basicConfig(format='%(asctime)s %(message)s')
下面的例子:
import logging
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.DEBUG)
logging.info('Logging app started')
logging.warning('An example logging message.')
logging.warning('Another log message')
输出:
2015-06-25 23:24:01,153 Logging app started
2015-06-25 23:24:01,153 An example message.
2015-06-25 23:24:01,153 Another message
Python subprocess
subprocess
模块使您可以从 Python 程序启动新应用程序。 多么酷啊?
在 Python 中启动一个进程:
您可以使用Popen
函数调用在 Python 中启动进程。 下面的程序启动 Unix 程序cat
,第二个参数是参数。 这相当于cat test.py
。您可以使用任何参数启动任何程序。
#!/usr/bin/env python
from subprocess import Popen, PIPE
process = Popen(['cat', 'test.py'], stdout=PIPE, stderr=PIPE)
stdout, stderr = process.communicate()
print stdout
process.communicate()
调用从进程中读取输入和输出。stdout
是进程输出。仅当发生错误时,stderr
才会被写入。 如果要等待程序完成,可以调用Popen.wait()
。
subprocess.call()
:
subprocess
具有方法call()
,可用于启动程序。该参数是一个列表,其第一个参数必须是程序名称。完整的定义是:
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
# Run the command described by args.
# Wait for command to complete, then return the returncode attribute.
在下面的示例中,完整的命令将为ls -l
#!/usr/bin/env python
import subprocess
subprocess.call(["ls", "-l"])
保存进程输出(标准输出)
我们可以获取程序的输出,并使用check_output
直接将其存储在字符串中。该方法定义为:
subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)
# Run command with arguments and return its output as a byte string.
用法示例:
#!/usr/bin/env python
import subprocess
s = subprocess.check_output(["echo", "Hello World!"])
print("s = " + s)
threading
和_thread
在 Python 中,您可以使用 Python 2.x 中的threading
模块或 Python 3 中的_thread
模块创建线程。我们将使用threading
模块与之交互。
线程是一种操作系统进程,具有与正常进程不同的功能:
- 线程作为进程的子集存在
- 线程共享内存和资源
- 进程具有不同的地址空间(在内存中)
什么时候使用线程处理? 通常,当您希望功能与程序同时出现时。 如果创建服务器软件,则希望服务器不仅侦听一个连接,而且侦听许多连接。 简而言之,线程使程序能够一次执行多个任务。
Python 线程
让我们创建一个线程程序。 在此程序中,我们将启动 10 个线程,每个线程将输出其 ID。
import threading
# Our thread class
class MyThread (threading.Thread):
def __init__(self,x):
self.__x = x
threading.Thread.__init__(self)
def run (self):
print str(self.__x)
# Start 10 threads.
for x in xrange(10):
MyThread(x).start()
输出:
0
1
...
9
如果运行一次,线程不必停止。 线程可以是定时的,每x
秒重复执行一次线程功能。
定时线程
在 Python 中,Timer
类是Thread
类的子类。 这意味着它的行为类似。我们可以使用计时器类来创建定时线程。计时器是通过.start()
方法调用启动的,就像常规线程一样。 下面的程序创建一个线程,该线程在 5 秒钟后启动。
#!/usr/bin/env python
from threading import *
def hello():
print "hello, world"
# create thread
t = Timer(10.0, hello)
# start thread after 10 seconds
t.start()
使用线程
重复执行功能我们可以像这样无休止地执行线程:
#!/usr/bin/env python
from threading import *
import time
def handleClient1():
while(True):
print "Waiting for client 1..."
time.sleep(5) # wait 5 seconds
def handleClient2():
while(True):
print "Waiting for client 2..."
time.sleep(5) # wait 5 seconds
# create threads
t = Timer(5.0, handleClient1)
t2 = Timer(3.0, handleClient2)
# start threads
t.start()
t2.start()
Python Lambda
我们可以创建匿名函数,称为 lambda 函数。 Lambda 函数与常规 Python 函数不同,它们源自 Lambda 演算。 它允许您编写非常简短的函数。
Lambda 函数示例
此代码显示 lambda 函数的用法:
#!/usr/bin/env python
f = lambda x : 2 * x
print f(3)
Lambda 函数从不使用return
语句,它总是返回。 Lambda 函数可能包含if
语句:
#!/usr/bin/env python
f = lambda x: x > 10
print(f(2))
print(f(12))
map
函数
map
的定义是map(function, iterable)
。它将函数应用于可迭代对象的每个项目。我们可以对列表和 lambda 函数使用map()
:
#!/usr/bin/env python
list = [1,2,3,4,5]
squaredList = map(lambda x: x*x, list)
print(squaredList)
在使用 lambda 函数的任何地方,都可以改用普通函数。 Lambda 函数不是语句,而是表达式。 Lambda 函数不支持语句块。
filter
函数
filter(function, iterable)
从元素中创建一个新列表,该函数为其返回True
。例:
#!/usr/bin/env python
list = [1,2,3,4,5,6,7,8,9,10]
newList = filter(lambda x: x % 2 == 0, list)
print(newList)
返回列表只包含 lambda 表达式lamba x: x % 2 == 0
为真的元素。
reduce
函数
函数reduce(function, iterable)
从左到右将函数应用在iterable
的各个项目上。 例:
#!/usr/bin/env python
list = [1,2,3,4,5]
s = reduce(lambda x,y: x+y, list)
print(s)
在这种情况下,表达式始终为真,因此它简单地汇总了列表中的元素。 另一个例子:
#!/usr/bin/env python
list = [10,6,7,5,2,1,8,5]
s = reduce(lambda x,y: x if (x > y) else y, list)
print(s)
Python 集合
Python 集合
Python 中的集合是对象的集合。 集合在 Python 2.4 和更高版本中可用。 它们与列表或元组的不同之处在于它们是根据数学集合建模的。
集合示例
要创建一个集合,我们使用set()
函数。
#!/usr/bin/env python
x = set(["Postcard", "Radio", "Telegram"])
print(x)
如果我们多次添加相同的item
元素,则会将其删除。 一个集合不能多次包含相同的元素。
#!/usr/bin/env python
x = set(["Postcard", "Radio", "Telegram", "Postcard"])
print(x)
简单记法
如果您使用 Python 2.6 版或更高版本,则可以使用简化的符号:
#!/usr/bin/env python
x = set(["Postcard", "Radio", "Telegram"])
print(x)
y = {"Postcard","Radio","Telegram"}
print(y)
集合方法
从集合清除元素
要从集合中删除所有元素:
#!/usr/bin/env python
x = set(["Postcard", "Radio", "Telegram"])
x.clear()
print(x)
将元素添加到集合中
要将元素添加到集合中:
#!/usr/bin/env python
x = set(["Postcard", "Radio", "Telegram"])
x.add("Telephone")
print(x)
将元素从集合中删除
要将元素从集合中删除:
!/usr/bin/env python
x = set(["Postcard", "Radio", "Telegram"])
x.remove("Radio")
print(x)
两个集合之间的差异
要查找两个集合之间的差异,请使用:
#!/usr/bin/env python
x = set(["Postcard", "Radio", "Telegram"])
y = set(["Radio","Television"])
print( x.difference(y) )
print( y.difference(x) )
请注意,x.difference(y)与 y.difference(x)不同。
子集
要测试集合是否为子集,请使用:
#!/usr/bin/env python
x = set(["a","b","c","d"])
y = set(["c","d"])
print( x.issubset(y) )
超集
要测试集合是否是超集,请执行以下操作:
#!/usr/bin/env python
x = set(["a","b","c","d"])
y = set(["c","d"])
print( x.issuperset(y) )
交集
要测试交集,请使用:
#!/usr/bin/env python
x = set(["a","b","c","d"])
y = set(["c","d"])
print( x.intersection(y) )
Python 模块
模块化编程
在进行编程时,该软件可以迅速扩展为大型代码库。 为了管理复杂性,我们可以使用类,函数和模块。
模块内容
要显示模块中的可访问函数(和包含的变量),可以使用以下代码:
#!/usr/bin/env python
import sys
print(dir(sys))
结果:
['__displayhook__', '__doc__', '__egginsert', '__excepthook__', '__name__', '__package__', '__plen', '__stderr__', '__stdin__',
'__stdout__', '_clear_type_cache', '_current_frames', '_getframe', '_mercurial', '_multiarch', 'api_version', 'argv',
'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dont_write_bytecode',
'exc_clear', 'exc_info', 'exc_type', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style'
, 'getcheckinterval', 'getdefaultencoding', 'getdlopenflags', 'getfilesystemencoding', 'getprofile', 'getrecursionlimit',
'getrefcount', 'getsizeof', 'gettrace', 'hexversion', 'long_info', 'maxint', 'maxsize', 'maxunicode', 'meta_path', 'modules',
'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'py3kwarning', 'pydebug', 'setcheckinterval', 'setdlopenflags'
, 'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'subversion', 'version', 'version_info',
'warnoptions']
创建一个模块
可以按照以下步骤创建自己的模块:
创建一个名为test.py
的文件(您的模块)
#!/usr/bin/env python
def add(a,b):
return a+b
然后创建一个名为app.py
的文件:
from test import *
print('hello')
print(add(5,2))
Python 图
介绍
数学和计算机科学中的图由节点组成,这些节点可以相互连接,也可以不相互连接。 节点之间的连接称为边。图可以是有向的(箭头)或无向的。 边可以表示距离或重量。
默认图(左),有向图(右)
Python 没有图数据类型。 要使用图,我们可以使用模块,也可以自己实现:
-
自己实现图
-
networkx
模块
Python 中的图
有向图可以定义为:
#!/usr/bin/env python
graph = {'A': ['B', 'C'],
'B': ['C', 'A'],
'C': ['D'],
'D': ['A']}
print(graph)
使用networkx
的图
networkx
软件模块支持创建,处理图。
#!/usr/bin/env python
import networkx as nx
G=nx.Graph()
G.add_node("A")
G.add_node("B")
G.add_node("C")
G.add_edge("A","B")
G.add_edge("B","C")
G.add_edge("C","A")
print("Nodes: " + str(G.nodes()))
print("Edges: " + str(G.edges()))
结果:
Nodes: [‘A’, ‘C’, ‘B’]
Edges: [(‘A’, ‘C’), (‘A’, ‘B’), (‘C’, ‘B’)]
Python 有限状态机
简介
有限状态机(FSM)是具有状态,转换,输入和输出的数学计算模型。 这台机器当时始终处于一种状态,并且可以通过转换转移到其他状态。 转换会将计算机的状态更改为另一个状态。
可以使用有限状态机对大量问题进行建模。 自动贩卖机,电梯和交通信号灯是现代生活中使用的状态机的简单示例。 高级用法是人工智能,语言解析和通信协议设计。
有限状态机示例
首先安装 Fysom 模块:
sudo pip install fysom
我们可以用两个状态定义一个有限状态机(FSM):睡眠状态和唤醒状态。 要在状态之间移动,我们将定义转换wakeup()
和sleep()
。
有限状态机。状态:醒着,睡觉。转换:睡眠,醒来
例:
from fysom import *
fsm = Fysom({'initial': 'awake',
'final': 'red',
'events': [
{'name': 'wakeup', 'src': 'sleeping', 'dst': 'awake'},
{'name': 'sleep', 'src': 'awake', 'dst': 'sleeping'}]})
print(fsm.current) # awake
fsm.sleep()
print(fsm.current) # sleeping
fsm.wakeup()
print(fsm.current) # awake
结果:
awake
sleeping
awake
有限状态机
Python 中有几种有限状态机的实现:
Python 树
介绍
在计算机科学中,树是模仿自然的数据结构。与自然界中的树不同,树数据结构是上下颠倒的:树的根在顶部。一棵树由节点组成,其连接称为边。 底部节点也称为叶节点。 一棵树可能没有循环。
一棵有八个节点的树。 树的根(5)在顶部。
Python 没有对树的内置支持。
二叉树
二叉树是一种数据结构,其中每个节点最多具有两个子代(左子代和右子代)。 一棵树的根在最上面。下面的每个节点都有一个以上的节点称为父节点。我们定义一个具有left
和right
属性的类Tree
。 从这个二叉树中,我们定义根(三个中的顶部)和一个左右节点。
#!/usr/bin/env python
class Tree(object):
def __init__(self):
self.left = None
self.right = None
self.data = None
root = Tree()
root.data = "root"
root.left = Tree()
root.left.data = "left"
root.right = Tree()
root.right.data = "right"
print(root.left.data)
然后,您可以像下面这样进一步创建树:
#!/usr/bin/env python
class Tree(object):
def __init__(self):
self.left = None
self.right = None
self.data = None
root = Tree()
root.data = "root"
root.left = Tree()
root.left.data = "left"
root.right = Tree()
root.right.data = "right"
root.left.left = Tree()
root.left.left.data = "left 2"
root.left.right = Tree()
root.left.right.data = "left-right"
二进制数和逻辑运算符
原文: https://pythonspot.com/binary-numbers-and-logical-operators/
我们之前已经看过简单的数字和运算。 在本文中,您将学习数字在计算机内部的工作方式以及与此相关的一些魔术 😃
更详细:虽然这在 Web 应用程序或大多数桌面应用程序中没有直接用处,但了解它非常有用。
在本文中,您将学习如何在 Python 中使用二进制数,如何将其转换为小数以及如何对它们进行按位运算。
二进制数
在最低层次上,计算机没有任何数字概念,除了“有信号”或“无信号”。您可以将其视为电灯开关:开关打开或关闭。
这些微小的信息,是您可以在计算机中存储的最小信息,称为位。我们将位表示为低(0)或高(1)。
为了表示大于 1 的数字,使用一系列位的主意诞生了。 一个八位的序列可以存储更大的数字,这称为字节。 由一和零组成的序列称为二进制。我们传统的十位数计数系统称为十进制。
二进制数及其十进制表示形式。
让我们在实践中看看:
# Prints out a few binary numbers.
print int('00', 2)
print int('01', 2)
print int('10', 2)
print int('11', 2)
第二个参数 2 告诉 Python 我们有一个基于 2 个元素(1 和 0)的数字。 要将字节(8 位)转换为十进制,只需在第一个参数中写入 8 位的组合即可。
# Prints out a few binary numbers.
print int('00000010', 2) # outputs 2
print int('00000011', 2) # outputs 3
print int('00010001', 2) # outputs 17
print int('11111111', 2) # outputs 255
电脑如何做到这一点? 每个数字(从右到左)乘以 2 的幂。
数字00010001
是(1 x 2^0) + (0 x 2^1) + (0 x 2^2) + (0 x 2^3) + (1 x 2^4) + (0 x 2^5) + (0 x 2^6) + (0 x 2^7) = 16 + 1 = 17
。记住,从右到左阅读。
数字00110010
是(0 x 2^0) + (1 x 2^1) + (0 x 2^2) + (0 x 2^3) + (**1** x 2^4) + (**1** x 2^5) + (0 x 2^6) + (0 x 2^7) = 32+16+2 = 50
。
自己尝试使用序列00101010
,以了解您是否了解并使用 Python 程序进行验证。
二进制数的逻辑运算
二进制左移和二进制右移
在二进制中,乘以因子 2 和除以因子 2 非常容易。 我们只需将位左移或右移。 我们向左下方移动:
位 4 | 位 3 | 位 2 | 位 1 |
---|---|---|---|
0 | 1 | 0 | 1 |
1 | 0 | 1 | 0 |
在移位(0,1,0,1
)之前,我们有数字 5。 移位(1,0,1,0
)后,我们得到数字 10。在 python 中,您可以使用按位向左运算符(<<
)向左移动,按位向右运算符(>>
) 向右移动。
inputA = int('0101',2)
print "Before shifting " + str(inputA) + " " + bin(inputA)
print "After shifting in binary: " + bin(inputA << 1)
print "After shifting in decimal: " + str(inputA << 1)
输出:
Before shifting 5 0b101
After shifting in binary: 0b1010
After shifting in decimal: 10
AND 运算符
给定两个输入,计算机可以使用这些位进行若干逻辑运算。让我们以 AND 运算符为例。 如果输入 A 和输入 B 为正,则输出将为正。 我们将以图形方式演示 AND 运算符,左边的两个是输入 A 和输入 B,右边的圆是输出:
按位 AND
在代码中,这就像使用&
符号一样简单,该符号代表逻辑 AND 运算符。
# This code will execute a bitwise logical AND. Both inputA and inputB are bits.
inputA = 1
inputB = 1
print inputA & inputB # Bitwise AND
通过更改输入,您将获得与上图相同的结果。 我们可以对一个序列执行 AND 运算符:
inputA = int('00100011',2) # define binary sequence inputA
inputB = int('00101101',2) # define binary sequence inputB
print bin(inputA & inputB) # logical AND on inputA and inputB and output in binary
输出:
0b100001 # equals 00100001
这是有道理的,因为如果您手动进行操作:
00100011
00101101
-------- Logical bitwise AND
00100001
OR 运算符
现在您已经了解了 AND 运算符,让我们看一下 OR 运算符。 给定两个输入,仅当 A 和 B 均为零时,输出才为零。
二进制按位 OR
要执行它,我们使用|
运算符。 可以像这样简单地执行一系列位:
inputA = int('00100011',2) # define binary number
inputB = int('00101101',2) # define binary number
print bin(inputA) # prints inputA in binary
print bin(inputB) # prints inputB in binary
print bin(inputA | inputB) # Execute bitwise logical OR and print result in binary
输出:
0b100011
0b101101
0b101111
XOR 运算符
这是一个有趣的运算符:异或或简称 XOR。
按位 XOR
为了执行它,我们使用^
运算符。 可以像这样简单地执行一系列位:
inputA = int('00100011',2) # define binary number
inputB = int('00101101',2) # define binary number
print bin(inputA) # prints inputA in binary
print bin(inputB) # prints inputB in binary
print bin(inputA ^ inputB) # Execute bitwise logical OR and print result in binary
输出:
0b100011
0b101101
0b1110
Python 调试
我们可以使用调试工具来最小化和发现错误。 在本文中,您将学习最佳的 Python 调试技巧。
PuDB - 基于控制台的 Python 调试器
使用 PuDB 进行 Python 调试
使用 PuDB 终端显示了图形界面。
安装
,以便与 Python 3 一起安装:
sudo pip3 install pudb
对于 Python 2.x 使用:
sudo pip install pudb
调试
使用以下命令开始调试:
$ pudb3 program.py
(或 sudo(如果您没有正确的权限))
您可以逐步完成该程序。 使用n
键逐步执行该程序。 当前变量内容显示在右上方。
python 调试
您可以使用b
键设置断点。 要继续执行直到下一个断点,请按c
键。
Python 程序中的断点
PDB - Python 调试器
pdb
模块支持设置断点。 断点是程序的有意暂停。 您可以在其中获取有关程序状态的更多信息。
要设置断点,请插入行
pdb.set_trace()
示例
实际示例:
import pdb
x = 3
y = 4
pdb.set_trace()
total = x + y
pdb.set_trace()
我们在该程序中插入了一些断点。 程序将在每个断点处暂停(pdb.set_trace()
)。 要查看变量内容,只需键入变量名称:
$ python3 program.py
(Pdb) x
3
(Pdb) y
4
(Pdb) total
*** NameError: name 'total' is not defined
(Pdb)
按c
或继续继续执行程序,直到下一个断点
(Pdb) c
--Return--
> program.py(7)<module>()->None
-> total = x + y
(Pdb) total
7
数据与数据库
创建并读取 csv
电子表格通常会导出 CSV(逗号分隔值)文件,因为它们易于读写。 CSV 文件仅由值,逗号和换行符组成。 该文件称为“逗号分隔值”文件,但您可以使用其他分隔符,例如竖线字符。
用 Python 创建电子表格文件(CSV)
让我们使用 Python 创建 CSV 格式的文件。 我们将使用逗号作为分隔符或除法符。
import csv
with open('persons.csv', 'wb') as csvfile:
filewriter = csv.writer(csvfile, delimiter=',',
quotechar='|', quoting=csv.QUOTE_MINIMAL)
filewriter.writerow(['Name', 'Profession'])
filewriter.writerow(['Derek', 'Software Developer'])
filewriter.writerow(['Steve', 'Software Developer'])
filewriter.writerow(['Paul', 'Manager'])
运行此代码将为我们提供以下内容的filpeople.csv
:
Name,Profession
Derek,Software Developer
Steve,Software Developer
Paul,Manager
您可以在您喜欢的 Office 程序中导入person.csv
文件。
用 Python 创建的电子表格文件
读取电子表格文件(csv)
如果您创建了 csv 文件,则可以使用以下代码逐行读取文件:
import csv
# open file
with open('persons.csv', 'rb') as f:
reader = csv.reader(f)
# read file row by row
for row in reader:
print row
这将简单地将每一行显示为列表:
['Name', 'Profession']
['Derek', 'Software Developer']
['Steve', 'Software Developer']
['Paul', 'Manager']
也许您想将其存储到 Python 列表中。 我们从 csv 文件中获取数据,然后将其存储到 Python 列表中。 我们使用if
语句跳过标题,因为它不属于列表。 完整代码:
import csv
# create list holders for our data.
names = []
jobs = []
# open file
with open('persons.csv', 'rb') as f:
reader = csv.reader(f)
# read file row by row
rowNr = 0
for row in reader:
# Skip the header row.
if rowNr >= 1:
names.append(row[0])
jobs.append(row[1])
# Increase the row number
rowNr = rowNr + 1
# Print data
print names
print jobs
结果:
['Derek', 'Steve', 'Paul']
['Software Developer', 'Software Developer', 'Manager']
大多数电子表格或 Office 程序都可以导出 csv 文件,因此我们建议您创建任何类型的 csv 文件并进行处理 😃
Python 数据库编程:SQLite(教程)
原文: https://pythonspot.com/python-database-programming-sqlite-tutorial/
在本教程中,您将学习如何在 Python 中使用 SQLite 数据库管理系统。 您将学习如何使用 SQLite,SQL 查询,RDBMS 以及更多有趣的东西!
Pyton 数据库
Python 数据库。
使用 SQL 语言从数据库系统检索数据。 数据无处不在,软件应用程序使用它。 数据位于内存,文件或数据库中。
Python 具有许多数据库系统的绑定,包括 MySQL, Postregsql, Oracle, Microsoft SQL Server 和 Maria DB。
这些数据库管理系统(DBMS)之一称为 SQLite。 SQLite 创建于 2000 年,是数据库动物园中众多管理系统之一。
SQL 是专用于管理数据库中保存的数据的专用编程语言。该语言自 1986 年以来一直存在,值得学习。这是关于 SQL 的古老有趣的视频。
SQLite
SQLite,一个关系数据库管理系统。SQLite 是世界上部署最广泛的 SQL 数据库引擎。SQLite 的源代码位于公共领域。
它是一个自包含,无服务器,零配置的事务型 SQL 数据库引擎。SQLite 项目由彭博社和 Mozilla 赞助。
安装 SQLite:
使用此命令安装 SQLite:
$ sudo apt-get install sqlite
验证是否正确安装。 复制此程序并将其另存为test1.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sqlite3 as lite
import sys
con = None
try:
con = lite.connect('test.db')
cur = con.cursor()
cur.execute('SELECT SQLITE_VERSION()')
data = cur.fetchone()
print "SQLite version: %s" % data
except lite.Error, e:
print "Error %s:" % e.args[0]
sys.exit(1)
finally:
if con:
con.close()
执行:
$ python test1.py
它应该输出:
SQLite version: 3.8.2
上面的脚本做了什么?
该脚本使用以下代码行连接到名为test.db
的新数据库:
con = lite.connect('test.db')
然后,它使用以下命令查询数据库管理系统
SELECT SQLITE_VERSION()
依次返回其版本号。 该行称为 SQL 查询。
SQL 创建和插入
下面的脚本会将数据存储到名为user.db
的新数据库中
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sqlite3 as lite
import sys
con = lite.connect('user.db')
with con:
cur = con.cursor()
cur.execute("CREATE TABLE Users(Id INT, Name TEXT)")
cur.execute("INSERT INTO Users VALUES(1,'Michelle')")
cur.execute("INSERT INTO Users VALUES(2,'Sonya')")
cur.execute("INSERT INTO Users VALUES(3,'Greg')")
SQLite 是使用表的数据库管理系统。 这些表可以与其他表建立关系:称为关系数据库管理系统或 RDBMS。 该表定义了数据的结构并可以保存数据。 数据库可以容纳许多不同的表。 使用以下命令创建表:
cur.execute("CREATE TABLE Users(Id INT, Name TEXT)")
我们使用以下命令将记录添加到表中:
cur.execute("INSERT INTO Users VALUES(2,'Sonya')")
cur.execute("INSERT INTO Users VALUES(3,'Greg')")
第一个值是 ID。 第二个值是名称。 一旦运行脚本,数据便被插入到数据库表Users
中:
SQL 表
SQLite 查询数据
我们可以使用两种方法浏览数据库:命令行和图形界面。
从控制台:要使用命令行进行浏览,请键入以下命令:
sqlite3 user.db
.tables
SELECT * FROM Users;
这将在表Users
中输出数据。
sqlite> SELECT * FROM Users;
1|Michelle
2|Sonya
3|Greg
从 GUI:如果要使用 GUI,则有很多选择。 我个人选择了 sqllite-man,但还有很多其他。我们使用以下方法安装:
sudo apt-get install sqliteman
我们启动应用程序 sqliteman。 gui 弹出。
sqliteman
按“文件 > 打开 > user.db
”。 似乎变化不大,不用担心,这只是用户界面。 左侧是一棵小树状视图,请按“表 > 用户”。 现在将显示包括所有记录的完整表格。
sqliteman
该 GUI 可用于修改表中的记录(数据)并添加新表。
SQL 数据库查询语言
SQL 有许多命令可以与数据库进行交互。 您可以从命令行或 GUI 尝试以下命令:
sqlite3 user.db
SELECT * FROM Users;
SELECT count(*) FROM Users;
SELECT name FROM Users;
SELECT * FROM Users WHERE id = 2;
DELETE FROM Users WHERE id = 6;
我们可以在 Python 程序中使用这些查询:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sqlite3 as lite
import sys
con = lite.connect('user.db')
with con:
cur = con.cursor()
cur.execute("SELECT * FROM Users")
rows = cur.fetchall()
for row in rows:
print row
这将从数据库输出Users
表中的所有数据:
$ python get.py
(1, u'Michelle')
(2, u'Sonya')
(3, u'Greg')
创建用户信息数据库
我们可以跨多个表构建数据。 这使我们的数据保持结构化,快速和有条理。 如果我们只有一个表来存储所有内容,那么很快就会陷入混乱。 我们将要做的是创建多个表并将它们组合使用。 我们创建两个表:
Users
:
SQL Table
Jobs
:
SQL Table
要创建这些表,您可以在 GUI 中手动进行操作或使用以下脚本:
# -*- coding: utf-8 -*-
import sqlite3 as lite
import sys
con = lite.connect('system.db')
with con:
cur = con.cursor()
cur.execute("CREATE TABLE Users(Id INT, Name TEXT)")
cur.execute("INSERT INTO Users VALUES(1,'Michelle')")
cur.execute("INSERT INTO Users VALUES(2,'Howard')")
cur.execute("INSERT INTO Users VALUES(3,'Greg')")
cur.execute("CREATE TABLE Jobs(Id INT, Uid INT, Profession TEXT)")
cur.execute("INSERT INTO Jobs VALUES(1,1,'Scientist')")
cur.execute("INSERT INTO Jobs VALUES(2,2,'Marketeer')")
cur.execute("INSERT INTO Jobs VALUES(3,3,'Developer')")
作业表有一个额外的参数Uid
。 我们使用它来连接 SQL 查询中的两个表:
SELECT users.name, jobs.profession FROM jobs INNER JOIN users ON users.ID = jobs.uid
您可以将该 SQL 查询合并到 Python 脚本中:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sqlite3 as lite
import sys
con = lite.connect('system.db')
with con:
cur = con.cursor()
cur.execute("SELECT users.name, jobs.profession FROM jobs INNER JOIN users ON users.ID = jobs.uid")
rows = cur.fetchall()
for row in rows:
print row
它应该输出:
$ python get2.py
(u'Michelle', u'Scientist')
(u'Howard', u'Marketeer')
(u'Greg', u'Developer')
您可能会喜欢:数据库和数据分析
MySQL 与 Python
在本教程中,您将学习如何在 Python 中使用广泛使用的数据库管理系统,称为 MySQL。您不需要使用 MySQL 的任何先验知识即可使用本教程,但是,除了本简短的入门教程所涵盖的内容外,MySQL 还有很多其他内容。
MySQL 教程
数据存储在表的集合中,每个表由一组行和列组成。 这类似于在 SQLite 中存储数据的方式。 为了与表中存储的数据进行交互,我们使用一种称为 SQL 的专用编程语言。
步骤 1:安装 MySQL
首先,您必须安装 MySQL 驱动程序,使用下面的特定安装方法。
在 Windows 上:
在 Linux 上:
使用以下命令安装 MySQLdb:
sudo apt-get install python-mysqldb
yum install mysql-python
取决于您的版本。
在 Mac 上:
必须先运行 MySQL 服务器,然后再进行下一步。
步骤 2:设置数据库
确保您具有数据库访问权限,可从命令行输入:
mysql -u USERNAME -p
然后,MySQL 将询问您的密码。 输入以下命令:
mysql> CREATE DATABASE pythonspot;
mysql> USE pythonspot;
我们继续创建表:
CREATE TABLE IF NOT EXISTS examples (
id int(11) NOT NULL AUTO_INCREMENT,
description varchar(45),
PRIMARY KEY (id)
);
然后,我们可以将数据插入表中(这些是 SQL 查询):
INSERT INTO examples(description) VALUES ("Hello World");
INSERT INTO examples(description) VALUES ("MySQL Example");
INSERT INTO examples(description) VALUES ("Flask Example");
现在,您可以使用 SQL 查询从表中获取所有记录:
mysql> SELECT * FROM examples;
+----+---------------+
| id | description |
+----+---------------+
| 1 | Hello World |
| 2 | MySQL Example |
| 3 | Flask Example |
+----+---------------+
3 rows in set (0.01 sec)
步骤 3:从 Python 获取数据
您可以使用 MySQLdb 模块直接从 Python 访问数据库。
#!/usr/bin/python
import MySQLdb
db = MySQLdb.connect(host="localhost", # your host
user="root", # username
passwd="root", # password
db="pythonspot") # name of the database
# Create a Cursor object to execute queries.
cur = db.cursor()
# Select data from table using SQL query.
cur.execute("SELECT * FROM examples")
# print the first and second columns
for row in cur.fetchall() :
print row[0], " ", row[1]
输出:
Hello World
MySQL Example
Flask Example
SqlAlchemy 和 ORM
对象关系映射器将关系数据库系统映射到对象。如果您不熟悉面向对象的编程,请先阅读本教程。ORM 与使用哪个关系数据库系统无关。在 Python 中,您可以与对象对话,ORM 会将其映射到数据库。在本文中,您将学习如何使用 SqlAlchemy ORM。
下图显示了 ORM 的功能:
ORM 对象关系映射。 我们使用 ORM 与数据库进行通信,并且仅使用 Python 对象和类。
创建一个类来填充 ORM
我们创建文件tabledef.py
。 在这个文件中,我们将定义一个Student
类。 下面是类的抽象可视化:
类定义
请注意,我们没有定义任何方法,仅定义了类的变量。 这是因为我们会将此类映射到数据库,因此不需要任何方法。
这是tabledef.py
的内容:
from sqlalchemy import *
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy import Column, Date, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, backref
engine = create_engine('sqlite:///student.db', echo=True)
Base = declarative_base()
########################################################################
class Student(Base):
""""""
__tablename__ = "student"
id = Column(Integer, primary_key=True)
username = Column(String)
firstname = Column(String)
lastname = Column(String)
university = Column(String)
#----------------------------------------------------------------------
def __init__(self, username, firstname, lastname, university):
""""""
self.username = username
self.firstname = firstname
self.lastname = lastname
self.university = university
# create tables
Base.metadata.create_all(engine)
执行:
python tabledef.py
ORM 创建了数据库文件tabledef.py
。 它将 SQL 查询输出到屏幕,在本例中显示为:
CREATE TABLE student (
id INTEGER NOT NULL,
username VARCHAR,
firstname VARCHAR,
lastname VARCHAR,
university VARCHAR,
PRIMARY KEY (id)
)
因此,当我们定义一个类时,ORM 为我们创建了数据库表。 该表仍然为空。
将数据插入数据库
数据库表仍然为空。 我们可以使用 Python 对象将数据插入数据库。 因为我们使用 SqlAlchemy ORM,所以我们不必编写单个 SQL 查询。 现在,我们只需创建要馈送到 ORM 的 Python 对象。 将下面的代码另存为dummy.py
import datetime
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from tabledef import *
engine = create_engine('sqlite:///student.db', echo=True)
# create a Session
Session = sessionmaker(bind=engine)
session = Session()
# Create objects
user = Student("james","James","Boogie","MIT")
session.add(user)
user = Student("lara","Lara","Miami","UU")
session.add(user)
user = Student("eric","Eric","York","Stanford")
session.add(user)
# commit the record the database
session.commit()
执行:
python dummy.py
ORM 会将 Python 对象映射到关系数据库。 这意味着您无需与应用程序进行任何直接交互,只需与对象进行交互即可。 如果您使用 SQLiteman 或 SQLite 数据库应用程序打开数据库,则会发现该表已创建:
数据表中的数据。
查询数据
我们可以使用以下代码查询表的所有项目。 请注意,Python 将每条记录视为Student
类定义的唯一对象。 将代码另存为demo.py
import datetime
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from tabledef import *
engine = create_engine('sqlite:///student.db', echo=True)
# create a Session
Session = sessionmaker(bind=engine)
session = Session()
# Create objects
for student in session.query(Student).order_by(Student.id):
print student.firstname, student.lastname
执行后,您将看到:
James Boogie
Lara Miami
Eric York
要选择单个对象,请使用filter()
方法。 下面的演示:
import datetime
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from tabledef import *
engine = create_engine('sqlite:///student.db', echo=True)
# create a Session
Session = sessionmaker(bind=engine)
session = Session()
# Select objects
for student in session.query(Student).filter(Student.firstname == 'Eric'):
print student.firstname, student.lastname
输出:
Eric York
最后,如果您不希望 ORM 输出,则任何 SQL 查询的输出都将create_engine
语句更改为:
engine = create_engine('sqlite:///student.db', echo=False)
Web
Python Web 开发
介绍
Web 应用程序通常是使用框架创建的。 框架使开发可扩展,可靠和可维护的 Web 应用程序变得更加容易。 这样可以避免一遍又一遍地重新创建相同的代码。
共同特征是:
- URL 路由
- 输出模板
- 数据库管理
- 会话管理
- 防范常见攻击
框架可以提供部分或全部这些功能。
例如,Flask Web 应用程序框架不支持数据库,您将需要一个单独的模块来使用数据库。 Django Web 应用程序框架默认支持数据库。
为什么要使用 Web 框架?
在进行 Web 开发时,您要避免花费时间在已经解决的事情上进行编程。 另一方面,如果您是经验丰富的 Web 开发人员,则 Web 框架可能无法提供您所需的一切。
存在哪些 Python Web 框架?
Django 和 Flask 是最受欢迎的Web框架。 但是,您可能需要评估框架。 概述:
最受欢迎的 python Web 应用程序框架是 Django,其次是 Flask。
在 Github 上提及框架的项目数量。
Django
Django 是最常用的 Python 网络框架。 它会处理很多事情,因此您可以专注于 Web 应用程序开发。 使用 Django 构建的网站处理的流量峰值很高,例如每秒 5 万次点击。
数据库访问是通过对象关系映射器实现的:您使用 Python 定义数据模型,而 Django 处理实际的数据库管理系统(SQL)。 但是,如果需要,您可以使用 Django 编写自己的 SQL 查询。 Django 支持 URL 路由。 它鼓励使用精美的 URL 设计,例如不带.php
或.asp
的结尾。
特性:
- 对象关系映射器
- 网址路由和视图
- 模板引擎
- 形式
- 认证方式
- 管理员
- 国际化
- 安全
如果您想进一步了解 Django,阅读这里。你知道 NASA,Bitbucket 和 Pinterest 的网站是用 Django 制作的嘛?
Flask
Flask 是一个通过设计模块化的 Python 微框架。 该框架旨在构建 Web 应用程序。 Flask 没有特定的数据库系统或 ORM 系统。 如果要使用数据库,则必须使用扩展。 Flask 通常与 SQLAlchemy 结合使用以用于数据库。
Flask 非常易于运行,一个最小的应用程序是:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
该框架支持 URL 路由,模板(使用 Jinja2),会话管理,并具有一些现成的安全性。
特性:
-
URL 路由和视图
-
模板引擎
-
会话管理
-
日志
如果您想进一步了解 Flask,阅读这里。您知道 Flask 最初是愚人节的笑话吗?
Python 托管
要在网络上运行您的应用,您需要托管。 除非您想自己托管,否则需要一个第三方来托管。
托管服务器:
Flask 入门:Hello World
在本教程中,您将学习如何使用 Python 构建网络应用。
我们将使用称为 Flask 的微型框架。它的核心很小,但是可以通过许多插件扩展,例如 SQLAlchemy,Babel,CouchDB,MongoDB 等。
一些 Flask 示例应用为:
安装 Flask
使用以下命令安装 Flask:
pip install Flask
Flask Hello World 应用程序
创建一个名为hello.py
的文件
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
最后,使用以下命令运行 Web 应用程序:
$ python hello.py
* Running on http://localhost:5000/
在您的网络浏览器中打开 http://localhost:5000/ ,然后会出现"Hello World!"
。
{% raw %}
Jinja2 模板引擎
Jinja2 是 Python 的模板引擎。 将数据呈现到网页时,可以使用它。 对于您访问的每个链接,您都希望使用格式显示数据。 通过使用模板引擎,我们可以将显示逻辑(html,css)与实际的 Python 代码分开。 让我们从一个例子开始
关于 Jinja
Jinja2 模板只是一个文本文件,不需要特定的扩展名,例如.html
,.xml
。模板可能包含标签和特殊定界符:
定界符 | 用法 |
---|---|
{% ... %} |
语句 |
{{ ... }} |
要打印到模板输出的表达式 |
{# ... #} |
注释未包含在模板输出中 |
# ... # |
行语句 |
在上面的示例中,我们有两个语句和一个表达式。 我们还没有包含任何注释。
基本模板和子模板
Jinja2 模板可以扩展基本模板。 在包含许多站点的网页上,您可能希望这些页面看起来相似。 在/templates/
中,使用以下代码创建一个名为base.html
的文件:
{% block head %}
<link rel="stylesheet" href="style.css">
{% title><block title %}{% endblock %} - My Webpage</title>
{% endblock %}
{% div id="content"><block content %}{% endblock %}</div>
<div id="footer">
{% block footer %}
Copyright 2015 by <a href="https://pythonspot.com/">pythonspot</a>.
{% endblock %}</div>
我们没有设置style.css
,但是您可以设置一个。将/templates/user.html
更改为:
{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
<style type="text/css">
.important { color: #336699; }
</style>
{% endblock %}
{% block content %}
<h1>Users</h1>
<p class="important"></p>
<ul>
{% for user in users %}
<li>{{ user }}</li>
{% endfor %}</ul>
{% endblock %}
通过以下方式重新启动应用程序:
python app.py
* Running on http://0.0.0.0:8080/
输出:
Flask Jinja 模板引擎
{% endraw %}
{% raw %}
Python 和 Flask Web 应用程序(入门教程)
使用 Flask 创建的 Python 应用
在本教程中,您将学习如何使用 Python 构建网络应用。 我们将使用称为 Flask 的微型框架。
为什么是 Flask?
-
易于使用。
-
内置开发服务器和调试器
-
集成单元测试支持
-
RESTful 请求分派
-
使用 Jinja2 模板
-
支持安全 cookie(客户端会话)
-
100%符合 WSGI 1.0
-
基于 Unicode
-
大量记录
创建 URL 路由
URL 路由使 Web 应用程序中的 URL 易于记住。 现在,我们将创建一些 URL 路由:
/hello
/members/
/members/name/
复制下面的代码,并将其另存为app.py
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "Index!"
@app.route("/hello")
def hello():
return "Hello World!"
@app.route("/members")
def members():
return "Members"
@app.route("/members/<string:name>/")
def getMember(name):
return name</string:name>
if __name__ == "__main__":
app.run()
使用以下命令重新启动应用程序:
$ python hello.py
* Running on http://localhost:5000/
在浏览器中尝试网址:
python-flask-webapp
Flask 页面模板
我们将使用称为模板的技术将代码和用户界面分开。 我们创建名为/templates/
的目录并创建模板:
<h1>Hello {{name}}</h1>
Python Flask 应用具有新的 URL 路由。 我们将默认端口更改为 80,即默认 HTTP 端口:
from flask import Flask, flash, redirect, render_template, request, session, abort
app = Flask(__name__)
@app.route("/")
def index():
return "Flask App!"
@app.route("/hello/<string:name>/")
def hello(name):
return render_template(
'test.html',name=name)</string:name>
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
You can then open : http://127.0.0.1/hello/Jackson/
给模板添加样式
您是否需要一些外观更好的模板? 我们修改文件:
{% extends "layout.html" %};
{% block body %};
<div class="block1">
<h1>Hello {{name}}!</h1>
<h2>Here is an interesting quote for you:</h2>
"The limits of my language are the limits of my mind. All I know is what I have words for."
<img src="http://www.naturalprogramming.cimg/smilingpython.gif">
</div>
{% endblock %};
然后,我们创建layout.html
来定义页面的外观。 (您可能想要拆分样式表和layout.html
文件)。将此复制为layout.html
<title>Website</title>
<style>
@import url(http://fonts.googleapis.com/css?family=Amatic+SC:700);</p>
<p>body{<br />
text-align: center;<br />
}<br />
h1{<br />
font-family: 'Amatic SC', cursive;<br />
font-weight: normal;<br />
color: #8ac640;<br />
font-size: 2.5em;<br />
}</p>
</style>{% block body %};{% endblock %};
重新启动应用程序并打开 URL:http://127.0.0.1/hello/Jackson/,您可以选择杰克逊以外的任何其他名字。
python webapp flask
传递变量
让我们显示随机引文,而不是总是相同的引文。我们将需要同时传递name
变量和quote
变量。要将多个变量传递给函数,我们只需执行以下操作:
return render_template(
'test.html',**locals())
我们新的test.html
模板如下所示:
{% extends "layout.html" %};
{% block body %};
<div class="block1">
<h1>Hello {{name}}!</h1>
<h2>Here is an interesting quote for you:</h2>
{{quote}}
<img src="http://www.naturalprogramming.cimg/smilingpython.gif">
</div>
{% endblock %};
我们将需要选择一个随机引文。 为此,我们使用以下代码:
quotes = [ "'If people do not believe that mathematics is simple, it is only because they do not realize how complicated life is.' -- John Louis von Neumann ",
"'Computer science is no more about computers than astronomy is about telescopes' -- Edsger Dijkstra ",
"'To understand recursion you must first understand recursion..' -- Unknown",
"'You look at things that are and ask, why? I dream of things that never were and ask, why not?' -- Unknown",
"'Mathematics is the key and door to the sciences.' -- Galileo Galilei",
"'Not everyone will understand your journey. Thats fine. Its not their journey to make sense of. Its yours.' -- Unknown" ]
randomNumber = randint(0,len(quotes)-1)
quote = quotes[randomNumber]
您看到的第一件事是我们定义了一个包含多个引文的数组。 这些可以作为quote[0]
,quote[1]
,quote[2]
等访问。函数randint()
返回一个介于 0 和引文总数之间的随机数,因为我们从零开始计数,所以减去了一个。最后,我们将quote
变量设置为计算机选择的引文。将以下代码复制到app.py
:
from flask import Flask, flash, redirect, render_template, request, session, abort
from random import randint
app = Flask(__name__)
@app.route("/")
def index():
return "Flask App!"
#@app.route("/hello/<string:name>")
@app.route("/hello/<string:name>/")
def hello(name):
# return name
quotes = [ "'If people do not believe that mathematics is simple, it is only because they do not realize how complicated life is.' -- John Louis von Neumann ",
"'Computer science is no more about computers than astronomy is about telescopes' -- Edsger Dijkstra ",
"'To understand recursion you must first understand recursion..' -- Unknown",
"'You look at things that are and ask, why? I dream of things that never were and ask, why not?' -- Unknown",
"'Mathematics is the key and door to the sciences.' -- Galileo Galilei",
"'Not everyone will understand your journey. Thats fine. Its not their journey to make sense of. Its yours.' -- Unknown" ]
randomNumber = randint(0,len(quotes)-1)
quote = quotes[randomNumber] </string:name></string:name>
return render_template(
'test.html',**locals())
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
重新启动应用程序时,它将随机返回这些引文之一。
python flask webap
接下来是什么?
您可以将您的站点链接到数据库系统,例如 MySQL,MariaDb 或 SQLite。 您可以在中找到 SQLite 教程。 享受创建您的应用程序的乐趣!
{% endraw %}
{% raw %}
Flask 和登录验证
Flask 图标
在本教程中,您将学习如何使用 Flask 和 Python 构建登录 Web 应用程序。
建立一个 Flask 登录页面
创建此 Python 文件并将其另存为app.py
:
from flask import Flask
from flask import Flask, flash, redirect, render_template, request, session, abort
import os
app = Flask(__name__)
@app.route('/')
def home():
if not session.get('logged_in'):
return render_template('login.html')
else:
return "Hello Boss!"
@app.route('/login', methods=['POST'])
def do_admin_login():
if request.form['password'] == 'password' and request.form['username'] == 'admin':
session['logged_in'] = True
else:
flash('wrong password!')
return home()
if __name__ == "__main__":
app.secret_key = os.urandom(12)
app.run(debug=True,host='0.0.0.0', port=4000)
在此处创建了两条路由(您可以在浏览器 URL 栏中看到的路径):
@app.route('/')
@app.route('/login', methods=['POST'])
第一个显示基于登录条件的登录屏幕或主屏幕。第二个路由在登录时验证登录变量。
我们创建目录/templates/
。 使用以下代码创建文件/templates/login.html
:
{% block body %};
{% if session['logged_in'] %};
You're logged in already!
{% else %};
<form action="/login" method="POST">
<input type="username" name="username" placeholder="Username">
<input type="password" name="password" placeholder="Password">
<input type="submit" value="Log in">
</form>
{% endif %};
{% endblock %};
{% endraw %};
使用以下命令运行 Web 应用程序:
$ python hello.py
在您的网络浏览器中打开 http://localhost:5000/ ,然后会出现登录屏幕。 登录凭据显示在do_admin_login()
函数中。
Pythonspot.com 登录界面
使它看起来很棒
功能正常时,登录屏幕看起来像 90 年代初期的用户界面(UI)。 我们从 codepen.io 中选择了一个随机登录模板。 我们使用文件style.css
创建目录/static/
。
* {
box-sizing: border-box;
}
*:focus {
outline: none;
}
body {
font-family: Arial;
background-color: #3498DB;
padding: 50px;
}
.login {
margin: 20px auto;
width: 300px;
}
.login-screen {
background-color: #FFF;
padding: 20px;
border-radius: 5px
}
.app-title {
text-align: center;
color: #777;
}
.login-form {
text-align: center;
}
.control-group {
margin-bottom: 10px;
}
input {
text-align: center;
background-color: #ECF0F1;
border: 2px solid transparent;
border-radius: 3px;
font-size: 16px;
font-weight: 200;
padding: 10px 0;
width: 250px;
transition: border .5s;
}
input:focus {
border: 2px solid #3498DB;
box-shadow: none;
}
.btn {
border: 2px solid transparent;
background: #3498DB;
color: #ffffff;
font-size: 16px;
line-height: 25px;
padding: 10px 0;
text-decoration: none;
text-shadow: none;
border-radius: 3px;
box-shadow: none;
transition: 0.25s;
display: block;
width: 250px;
margin: 0 auto;
}
.btn:hover {
background-color: #2980B9;
}
.login-link {
font-size: 12px;
color: #444;
display: block;
margin-top: 12px;
}
将login.html
模板修改为:
<link rel="stylesheet" href="/static/style.css" type="text/css">
{% block body %};
<form action="/login" method="POST">
<div class="login">
<div class="login-screen">
<div class="app-title">
<h1>Login</h1>
</div>
<div class="login-form">
<div class="control-group">
<input type="text" class="login-field" value="" placeholder="username" name="username">
<label class="login-field-icon fui-user" for="login-name"></label></div>
<div class="control-group">
<input type="password" class="login-field" value="" placeholder="password" name="password">
<label class="login-field-icon fui-lock" for="login-pass"></label></div>
<input type="submit" value="Log in" class="btn btn-primary btn-large btn-block">
</div>
</div>
</div>
</form>
{% endblock %};
重新启动应用程序后,将出现以下屏幕:
Python Flask 登录界面
很棒,不是吗? 😃
那么注销呢?
如您所见,没有注销按钮或功能。 创建起来非常容易。 下面提出的解决方案只是众多解决方案之一。 我们创建一个新的路由/logout
,它直接指向函数logout()
。 此函数清除会话变量并返回登录屏幕。
@app.route("/logout")
def logout():
session['logged_in'] = False
return home()
完整代码:
from flask import Flask
from flask import Flask, flash, redirect, render_template, request, session, abort
import os
app = Flask(__name__)
@app.route('/')
def home():
if not session.get('logged_in'):
return render_template('login.html')
else:
return "Hello Boss! <a href="/logout">Logout</a>"
@app.route('/login', methods=['POST'])
def do_admin_login():
if request.form['password'] == 'password' and request.form['username'] == 'admin':
session['logged_in'] = True
else:
flash('wrong password!')
return home()
@app.route("/logout")
def logout():
session['logged_in'] = False
return home()
if __name__ == "__main__":
app.secret_key = os.urandom(12)
app.run(debug=True,host='0.0.0.0', port=4000)
连接数据库
如果要使用多用户登录系统,则应在应用程序中添加一个数据库层。Flask 没有现成的数据库支持。 如果要数据库支持,则必须使用第三方库。 在本教程中,我们将使用 SqlAlchemy。 如果您没有安装,请执行以下操作:
$ sudo pip install Flask-SqlAlchemy
SQLAlchemy 是用于 Python 编程语言的 SQL 工具箱和对象关系映射器(ORM)。 它支持 MySQL,Microsoft SQL Server 和许多其他关系数据库管理系统。 如果您不熟悉所有这些术语,请继续阅读。
创建文件tabledef.py
:
from sqlalchemy import *
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy import Column, Date, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, backref
engine = create_engine('sqlite:///tutorial.db', echo=True)
Base = declarative_base()
########################################################################
class User(Base):
""""""
__tablename__ = "users"
id = Column(Integer, primary_key=True)
username = Column(String)
password = Column(String)
#----------------------------------------------------------------------
def __init__(self, username, password):
""""""
self.username = username
self.password = password
# create tables
Base.metadata.create_all(engine)
使用以下命令执行:
python tabledef.py
该文件将创建数据库结构。在目录内,您将找到一个名为tutorial.db
的文件。创建一个名为dummy.py
的文件,其中将包含以下代码:
import datetime
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from tabledef import *
engine = create_engine('sqlite:///tutorial.db', echo=True)
# create a Session
Session = sessionmaker(bind=engine)
session = Session()
user = User("admin","password")
session.add(user)
user = User("python","python")
session.add(user)
user = User("jumpiness","python")
session.add(user)
# commit the record the database
session.commit()
session.commit()
执行:
$ python dummy.py
这会将伪数据放入数据库中。 最后,我们更新app.py
使用 SqlAlchemy 验证登录凭据
下一步是编写验证数据库中存在的用户和密码的功能。 使用 SqlAlchemy 我们可以做到这一点(虚拟/伪代码):
@app.route('/test')
def test():
POST_USERNAME = "python"
POST_PASSWORD = "python"
Session = sessionmaker(bind=engine)
s = Session()
query = s.query(User).filter(User.username.in_([POST_USERNAME]), User.password.in_([POST_PASSWORD]) )
result = query.first()
if result:
return "Object found"
else:
return "Object not found " + POST_USERNAME + " " + POST_PASSWORD
我们使用 SqlAlchemys Oject 关系映射(ORM)。 我们将对象映射到关系数据库表,反之亦然。 定义(用户)在tabledef.py
中给出。s.query
函数是构建查询的地方。 我们有两个条件:用户名和密码必须匹配。 如果对象存在,query.first()
返回true
,否则返回false
。 这给出了以下总代码:
from flask import Flask
from flask import Flask, flash, redirect, render_template, request, session, abort
import os
from sqlalchemy.orm import sessionmaker
from tabledef import *
engine = create_engine('sqlite:///tutorial.db', echo=True)
app = Flask(__name__)
@app.route('/')
def home():
if not session.get('logged_in'):
return render_template('login.html')
else:
return "Hello Boss! <a href="/logout">Logout</a>"
@app.route('/login', methods=['POST'])
def do_admin_login():
POST_USERNAME = str(request.form['username'])
POST_PASSWORD = str(request.form['password'])
Session = sessionmaker(bind=engine)
s = Session()
query = s.query(User).filter(User.username.in_([POST_USERNAME]), User.password.in_([POST_PASSWORD]) )
result = query.first()
if result:
session['logged_in'] = True
else:
flash('wrong password!')
return home()
@app.route("/logout")
def logout():
session['logged_in'] = False
return home()
if __name__ == "__main__":
app.secret_key = os.urandom(12)
app.run(debug=True,host='0.0.0.0', port=4000)
现在,您可以使用数据库表中定义的任何用户登录。
那么安全性呢?
我们在上面演示了一个简单的登录应用程序。 但是,正确保护它是您的工作。 有很多人会尝试闯入您的应用程序。
最佳做法:
使用 Google 登录到您的 Flask 应用
在本文中,您将学习如何在 Flask 应用中使用 Google 进行登录身份验证。 您可以使用 Google 来对您的网站进行身份验证,而不是使用自定义用户登录系统。 您的访问者可能已经在 Google 上拥有一个帐户,为什么不使用它登录?
为此,我们使用称为 OAuth 的协议。 从维基百科:
OAuth 是一种使用令牌来代表资源所有者访问资源的协议。 考虑使用户能够对网站的某些部分发出代客密钥。 许多网站,例如 Google,Facebook 和 Twitter,都使用 OAuth 来认证第三方客户端,以便访问某些用户资源。
如果听起来含糊,请放心,我们将逐步指导您。
使用 Google 的登录验证
我们使用名为flask_oauth
的模块向 Google 进行身份验证。 它由 Flask 的创建者 Armin Ronacher 维护,因此可以确保该模块不会消失。 该模块使用 OAuth,该协议提供令牌以访问资源。 其他模块可能没有很好的支持。
复制下面的代码,并设置您从上面的 Google 获得的客户端 ID 和客户端密钥。 只需替换以下行:
GOOGLE_CLIENT_ID = 'PUT CLIENT ID'
GOOGLE_CLIENT_SECRET = 'PUT CLIENT SECRET'
将程序另存为app.py
from flask import Flask, redirect, url_for, session
from flask_oauth import OAuth
# You must configure these 3 values from Google APIs console
# https://code.google.com/apis/console
GOOGLE_CLIENT_ID = 'PUT CLIENT ID'
GOOGLE_CLIENT_SECRET = 'PUT CLIENT SECRET'
REDIRECT_URI = '/oauth2callback' # one of the Redirect URIs from Google APIs console
SECRET_KEY = 'development key'
DEBUG = True
app = Flask(__name__)
app.debug = DEBUG
app.secret_key = SECRET_KEY
oauth = OAuth()
google = oauth.remote_app('google',
base_url='https://www.google.com/accounts/',
authorize_url='https://accounts.google.com/o/oauth2/auth',
request_token_url=None,
request_token_params={'scope': 'https://www.googleapis.com/auth/userinfo.email',
'response_type': 'code'},
access_token_url='https://accounts.google.com/o/oauth2/token',
access_token_method='POST',
access_token_params={'grant_type': 'authorization_code'},
consumer_key=GOOGLE_CLIENT_ID,
consumer_secret=GOOGLE_CLIENT_SECRET)
@app.route('/')
def index():
access_token = session.get('access_token')
if access_token is None:
return redirect(url_for('login'))
access_token = access_token[0]
from urllib2 import Request, urlopen, URLError
headers = {'Authorization': 'OAuth '+access_token}
req = Request('https://www.googleapis.com/oauth2/v1/userinfo',
None, headers)
try:
res = urlopen(req)
except URLError, e:
if e.code == 401:
# Unauthorized - bad token
session.pop('access_token', None)
return redirect(url_for('login'))
return res.read()
return res.read()
@app.route('/login')
def login():
callback=url_for('authorized', _external=True)
return google.authorize(callback=callback)
@app.route(REDIRECT_URI)
@google.authorized_handler
def authorized(resp):
access_token = resp['access_token']
session['access_token'] = access_token, ''
return redirect(url_for('index'))
@google.tokengetter
def get_access_token():
return session.get('access_token')
def main():
app.run()
if __name__ == '__main__':
main()
使用以下命令执行:
python app.py
* Running on http://127.0.0.1:5000/
* Restarting with reloader
然后,您可以打开链接以查看登录屏幕。 一旦接受,该应用程序将仅返回以 JSON 格式编码的您的帐户信息。
使用 Google 登录到您的 Flask 应用
最后,您可以验证是否在新路由上设置了访问令牌。
{% raw %}
使用 Twitter 登录 Flask 应用
在本教程中,您将学习如何在 Flask 应用程序中使用 Twitter 进行登录身份验证。 您可以使用 Twitter 对网站进行身份验证,而不是使用自定义用户登录系统。 您的访客可能已经在 Twitter 上拥有一个帐户,那么为什么不使用它登录呢?
为此,我们使用称为 OAuth 的协议。 从维基百科:
OAuth 是一种使用令牌来代表资源所有者访问资源的协议。 考虑使用户能够对网站的某些部分发出代客密钥。 许多网站,例如 Google,Facebook 和 Twitter,都使用 OAuth 来认证第三方客户端,以便访问某些用户资源。
如果听起来含糊,请放心,我们将逐步指导您。
代码
创建文件app.py
,并设置您从 Twitter 获得的consumer_key
和consumer_secret
。
from flask import Flask, request, redirect, url_for, session, g, flash, \
render_template
from flask_oauth import OAuth
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
# configuration
SECRET_KEY = 'development key'
DEBUG = True
# setup flask
app = Flask(__name__)
app.debug = DEBUG
app.secret_key = SECRET_KEY
oauth = OAuth()
# Use Twitter as example remote application
twitter = oauth.remote_app('twitter',
# unless absolute urls are used to make requests, this will be added
# before all URLs. This is also true for request_token_url and others.
base_url='https://api.twitter.com/1/',
# where flask should look for new request tokens
request_token_url='https://api.twitter.com/oauth/request_token',
# where flask should exchange the token with the remote application
access_token_url='https://api.twitter.com/oauth/access_token',
# twitter knows two authorizatiom URLs. /authorize and /authenticate.
# they mostly work the same, but for sign on /authenticate is
# expected because this will give the user a slightly different
# user interface on the twitter side.
authorize_url='https://api.twitter.com/oauth/authenticate',
# the consumer keys from the twitter application registry.
consumer_key='ADD TWITTER CONSUMER KEY',
consumer_secret='ADD TWITTER CONSUMER SECRET'
)
@twitter.tokengetter
def get_twitter_token(token=None):
return session.get('twitter_token')
@app.route('/')
def index():
access_token = session.get('access_token')
if access_token is None:
return redirect(url_for('login'))
access_token = access_token[0]
return render_template('index.html')
@app.route('/login')
def login():
return twitter.authorize(callback=url_for('oauth_authorized',
next=request.args.get('next') or request.referrer or None))
@app.route('/logout')
def logout():
session.pop('screen_name', None)
flash('You were signed out')
return redirect(request.referrer or url_for('index'))
@app.route('/oauth-authorized')
@twitter.authorized_handler
def oauth_authorized(resp):
next_url = request.args.get('next') or url_for('index')
if resp is None:
flash(u'You denied the request to sign in.')
return redirect(next_url)
access_token = resp['oauth_token']
session['access_token'] = access_token
session['screen_name'] = resp['screen_name']
session['twitter_token'] = (
resp['oauth_token'],
resp['oauth_token_secret']
)
return redirect(url_for('index'))
if __name__ == '__main__':
app.run()
使用文件index.html
创建目录/templates/
{% block body %};
<h2>Flask Login App</h2>
{% if session['screen_name'] %};
Hello {{ session['screen_name'] };};!
{% else %};
Sign in with twitter.
<a href="{{ url_for('login') };};"><img src="{{
url_for('static', filename='sign-in.png') };}; alt="sign in"></a>
{% endif %};
{% endblock %};
最后,使用图像sign-in.png
创建目录/static/
:
通过以下方式启动您的应用:
python app.py
在您的网络浏览器中打开该应用程序。 然后,您的用户只需按照以下步骤登录:
Flask Twitter 登录界面
Flask OAuth Twitter
Twitter OAuth
{% endraw %}
Flask,JSON 和 Google Charts API
原文: https://pythonspot.com/flask-json-and-the-google-charts-api/
本教程将教您如何构建结合 JSON 和 Google Charts API 的 Flask 应用。 如果您在阅读 Flask 之前没有任何经验,我建议您阅读以前的教程,那么它们会很有趣!
获取 JSON 数据
要显示很棒的图表,我们首先需要一些数据。有两种常见的方法可以在 Web 应用程序中获取数据:使用 API(通常为 JSON)的服务器中的数据和数据库中的数据。 我使用 Fixer.io JSON API 来获取一些财务数据,但是任何 JSON API 都可以。 如果您不熟悉 JSON,请参阅此文章。
我们编写此脚本来获取汇率:
import json
import urllib2
def getExchangeRates():
rates = []
response = urllib2.urlopen('http://api.fixer.io/latest')
data = response.read()
rdata = json.loads(data, parse_float=float)
rates.append( rdata['rates']['USD'] )
rates.append( rdata['rates']['GBP'] )
rates.append( rdata['rates']['JPY'] )
rates.append( rdata['rates']['AUD'] )
return rates
rates = getExchangeRates()
print rates
使用 Flask 的 Google Charts API
使用 Google Charts API,您可以在网站上显示实时数据。有很多很棒的图表可以轻松添加到 Flask 应用中。我们只需将通过 JSON 从服务器获取并解析的数据提供给 Google Charts API。
为目录创建带有目录/templates/
的 flask 应用程序。 这是 Flask 的主要代码:
from flask import Flask, flash, redirect, render_template, request, session, abort
import os
import json
import urllib2
tmpl_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')
app = Flask(__name__, template_folder=tmpl_dir)
def getExchangeRates():
rates = []
response = urllib2.urlopen('http://api.fixer.io/latest')
data = response.read()
rdata = json.loads(data, parse_float=float)
rates.append( rdata['rates']['USD'] )
rates.append( rdata['rates']['GBP'] )
rates.append( rdata['rates']['HKD'] )
rates.append( rdata['rates']['AUD'] )
return rates
@app.route("/")
def index():
rates = getExchangeRates()
return render_template('test.html',**locals())
@app.route("/hello")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
我们有这个模板:
{% block body %}
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<div id="chart_div" style="width: 900px; height: 300px;">
<div>
<script type="text/javascript">//<![CDATA[
google.load('visualization', '1', {packages: ['corechart', 'bar']});<br />
google.setOnLoadCallback(drawBasic);</p>
<p>function drawBasic() {</p>
<p> var data = google.visualization.arrayToDataTable([<br />
['Currency', 'Rate', { role: 'style' }],<br />
['USD', { {rates[0]}}, 'gold'],<br />
['GBP', { {rates[1]}}, 'silver'],<br />
['HKD', { {rates[2]}}, 'brown'],<br />
['AUD', { {rates[3]}}, 'blue']<br />
]);</p>
<p> var options = {<br />
title: 'Exchange rate overview',<br />
chartArea: {width: '50%'},<br />
hAxis: {<br />
title: '',<br />
minValue: 0<br />
},<br />
vAxis: {<br />
title: ''<br />
}<br />
};</p>
<p> var chart = new google.visualization.BarChart(document.getElementById('chart_div'));</p>
<p> chart.draw(data, options);<br />
}<br />
//]]> </p>
<p></script>
{% endblock %}
结果:
Flask App
{% raw %}
Flask 网页表单
Flask web 表单
在本教程中,您将学习如何使用 Flask 进行表单验证。 表单在所有 Web 应用程序中都扮演着重要角色。
我们使用 WTForms,这是用于验证表单的模块。 我们将从一个简单的表格开始,其中包含一个要求输入名称的字段。
CSS 与 Flask
我们使用 Bootstrap 来设置表单的样式。Bootstrap 是流行的 HTML,CSS 和 JS 框架,用于在 Web 上开发响应式,移动优先项目。 它使前端 Web 开发更快,更轻松。 输出将是:
Flask wtforms
您可以从 http://getbootstrap.com/getting-started/#download 获取引导文件,并将其解压缩到新目录/static/
中。 代码几乎相同,但是模板已更改。 代码:
from flask import Flask, render_template, flash, request
from wtforms import Form, TextField, TextAreaField, validators, StringField, SubmitField
# App config.
DEBUG = True
app = Flask(__name__)
app.config.from_object(__name__)
app.config['SECRET_KEY'] = '7d441f27d441f27567d441f2b6176a'
class ReusableForm(Form):
name = TextField('Name:', validators=[validators.required()])
@app.route("/", methods=['GET', 'POST'])
def hello():
form = ReusableForm(request.form)
print form.errors
if request.method == 'POST':
name=request.form['name']
print name
if form.validate():
# Save the comment here.
flash('Hello ' + name)
else:
flash('Error: All the form fields are required. ')
return render_template('hello.html', form=form)
if __name__ == "__main__":
app.run()
我们在模板hello.html
中添加了 Bootstrap:
<title>Reusable Form Demo</title>
<link rel="stylesheet" media="screen" href="static/bootstrap.min.css">
<link rel="stylesheet" href="static/bootstrap-theme.min.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<div class="container">
<h2>Flask Web Form</h2>
<form action="" method="post" role="form">
{{ form.csrf }}
<div class="form-group">
<label for="name">Name:</label>
<input type="text" class="form-control" id="name" name="name" placeholder="What's your name?"></div>
<button type="submit" class="btn btn-success">Submit</button>
</form>{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for message in messages %}
{% if "Error" not in message[1]: %}
<div class="alert alert-info">
<strong>Success! </strong> {{ message[1] }}</div>
{% endif %}
{% if "Error" in message[1]: %}
<div class="alert alert-warning">
{{ message[1] }}</div>
{% endif %}
{% endfor %}
{% endif %}
{% endwith %}
</div>
Flask 注册表
我们使用相同的原理来创建注册表,要求输入姓名,电子邮件和密码。 我们更新Form
类:
class ReusableForm(Form):
name = TextField('Name:', validators=[validators.required()])
email = TextField('Email:', validators=[validators.required(), validators.Length(min=6, max=35)])
password = TextField('Password:', validators=[validators.required(), validators.Length(min=3, max=35)])
def reset(self):
blankData = MultiDict([ ('csrf', self.reset_csrf() ) ])
self.process(blankData)
我们可以使用以下方法传递变量:
name=request.form['name']
password=request.form['password']
email=request.form['email']
完整代码:
from flask import Flask, render_template, flash, request
from wtforms import Form, TextField, TextAreaField, validators, StringField, SubmitField
# App config.
DEBUG = True
app = Flask(__name__)
app.config.from_object(__name__)
app.config['SECRET_KEY'] = '7d441f27d441f27567d441f2b6176a'
class ReusableForm(Form):
name = TextField('Name:', validators=[validators.required()])
email = TextField('Email:', validators=[validators.required(), validators.Length(min=6, max=35)])
password = TextField('Password:', validators=[validators.required(), validators.Length(min=3, max=35)])
@app.route("/", methods=['GET', 'POST'])
def hello():
form = ReusableForm(request.form)
print form.errors
if request.method == 'POST':
name=request.form['name']
password=request.form['password']
email=request.form['email']
print name, " ", email, " ", password
if form.validate():
# Save the comment here.
flash('Thanks for registration ' + name)
else:
flash('Error: All the form fields are required. ')
return render_template('hello.html', form=form)
if __name__ == "__main__":
app.run()
使用以下代码更新模板hello.html
:
<title>Reusable Form Demo</title>
<link rel="stylesheet" media="screen" href="static/bootstrap.min.css">
<link rel="stylesheet" href="static/bootstrap-theme.min.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<div class="container">
<h2>Flask Web Form</h2>
<form action="" method="post" role="form">
{{ form.csrf }}
<div class="form-group">
<label for="name">Name:</label>
<input type="text" class="form-control" id="name" name="name" placeholder="What's your name?">
<label for="email">Email:</label>
<input type="text" class="form-control" id="email" name="email" placeholder="Your email will be used to contact you.">
<label for="password">Password:</label>
<input type="password" class="form-control" id="password" name="password" placeholder="Enter a password.">
</div>
<button type="submit" class="btn btn-success">Sign Up</button>
</form>{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for message in messages %}
{% if "Error" not in message[1]: %}
<div class="alert alert-info">
<strong>Success! </strong> {{ message[1] }}</div>
{% endif %}
{% if "Error" in message[1]: %}
<div class="alert alert-warning">
{{ message[1] }}</div>
{% endif %}
{% endfor %}
{% endif %}
{% endwith %}
</div>
输出:
flask 表单 bootstrap
WTForms 可以验证电子邮件,密码,数字等等。 有关验证器的列表,请参见:http://wtforms.readthedocs.org/en/latest/validators.html。
{% endraw %}
Flask 和静态 html 文件
您可以使用 Flask 框架并一起使用静态文件。
Flask 将为您提供 URL 路由,许多功能以及所有 Python 好处。
您可能需要一个部分动态和部分静态的应用程序。 或者,您可能只想使用 URL 路由进行浏览。 在本文中,我们将教您如何使用 Flask 加载静态 HTML 文件。
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/<string:page_name>/')
def render_static(page_name):
return render_template('%s.html' % page_name)</string:page_name>
if __name__ == '__main__':
app.run()
该应用程序使用以下方法初始化 Flask 应用程序:
app.run()
该应用程序为任何可能的页面创建 URL 路由,并使用以下链接将其链接到静态 html 文件:
@app.route('/<string:page_name>/')
def render_static(page_name):
return render_template('%s.html' % page_name)
/<string:page_name>/
创建目录/templates/
并添加文件hello.html
:
<title>Hello World Template</title>
Hello World
使用以下命令启动服务器:
$ python app.py
* Running on http://127.0.0.1:5000/
然后,可以使用 URL 路由访问任何.html
文件。
例如,可以使用 http://127.0.0.1:5000/hello 访问静态文件hello.html
。 您可以将任何 css 文件存储在/static/
目录中。
Flask 模板,SQLAlchemy 和 Bootstarp
原文: https://pythonspot.com/flask-boilerplate-with-bootstrap-sqlalchemy/
在本文中,您将学习cookiecutter
,这是一个从项目模板创建项目的命令行实用程序。 使用cookiecutter
,您可以创建一个新的 python Flask 项目。 这类似于标准的 Flask 项目,除了使用此方法时,您将从几个完整的模板和功能列表开始。
特性
- 具有入门模板的 Bootstrap 3 和 Font Awesome 4
- 具有基本用户模型的 Flask-SQLAlchemy
- 使用 Flask-Migrate 轻松进行数据库迁移
- 带登录和注册表格的 Flask-WTForms
- Flask-Login 进行身份验证
- Flask-Bcrypt 用于密码哈希
- 用于部署到 PaaS 的 Procfile(例如 Heroku)
- pytest 和 Factory-Boy 进行测试(包括示例测试)
- 一个简单的
manage.py
脚本。 - 使用 Flask-Assets 缩小 CSS 和 JS
- 可选的 Bower 支持前端程序包管理
- 使用 Flask-Cache 进行缓存
- 有用的调试工具栏
- 利用最佳实践:蓝图和 Application Factory 模式
安装 Flask 依赖项:
sudo pip install flask_script
sudo pip install flask_migrate
sudo pip install flask_assets
sudo pip install flask_bcrypt
sudo pip install flask_cache
sudo pip install flask_debugtoolbar
安装并克隆cookieclutter
sudo pip install cookiecutter
sudo pip install mock==1.0.1
cookiecutter https://github.com/sloria/cookiecutter-flask.git
系统将询问您有关项目的一些信息,并根据需要输入:
remote: Counting objects: 1545, done.
remote: Total 1545 (delta 0), reused 0 (delta 0), pack-reused 1545
Receiving objects: 100% (1545/1545), 1.57 MiB | 720.00 KiB/s, done.
Resolving deltas: 100% (857/857), done.
Checking connectivity... done.
full_name (default is "Steven Loria")? Steven Loria
email (default is "[email protected]")? [email protected]
github_username (default is "sloria")? sloria
project_name (default is "My Flask App")? example
app_name (default is "myflaskapp")? example
project_short_description (default is "A flasky app.")? a flasky app
然后输入您的项目目录(示例)并启动服务器
cd example
python manage.py runserver
然后,您可以打开 http://127.0.0.1:5000
cookiecutter
输出主题
Flask 和使用 Chart.js 的美观的图表
原文: https://pythonspot.com/flask-and-great-looking-charts-using-chart-js/
带有饼图的 Flask webapp
在本文中,您将学习如何使用 Chart.js 和 [Flask](/ python-flask-tutorials)。
Chart.js 是一个 JavaScript 库,用于创建简单干净的图表。它们都是基于 HTML5 的,响应式的,模块化的,交互式的,共有 6 个图表。
<meta charset="utf-8"> <title>Chart.js </title> <!-- import plugin script --> <script src="static/Chart.min.js"></script>
<h1>Flask Chart.js</h1>
<!-- bar chart canvas element --><canvas id="chart" width="600" height="400"></canvas>
<script><br />
// bar chart data<br />
var barData = {<br />
labels : [],<br />
datasets : [<br />
{<br />
fillColor: "rgba(151,187,205,0.2)",<br />
strokeColor: "rgba(151,187,205,1)",<br />
pointColor: "rgba(151,187,205,1)",<br />
data : []<br />
}<br />
]<br />
}</p>
<p> // get bar chart canvas<br />
var mychart = document.getElementById("chart").getContext("2d");</p>
<p> steps = 10<br />
max = 10<br />
// draw bar chart<br />
new Chart(mychart).Bar(barData, {<br />
scaleOverride: true,<br />
scaleSteps: steps,<br />
scaleStepWidth: Math.ceil(max / steps),<br />
scaleStartValue: 0,<br />
scaleShowVerticalLines: true,<br />
scaleShowGridLines : true,<br />
barShowStroke : true,<br />
scaleShowLabels: true<br />
});</p>
<p></script>
创建目录/static/
并将文件Chart.min.js
添加到其中。您可以从 Chart.js 网站获得它,也可以使用链接。 最后进入主目录并使用以下内容创建app.py
:
from flask import Flask
from flask import Markup
from flask import Flask
from flask import render_template
app = Flask(__name__)
@app.route("/")
def chart():
labels = ["January","February","March","April","May","June","July","August"]
values = [10,9,8,7,6,4,7,8]
return render_template('chart.html', values=values, labels=labels)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5001)
最后运行:
python app.py
打开 http://127.0.0.1:5001/,您会看到数组values[]
与数据中的labels[]
一起绘制。
我们只需将这两个数组传递给render_template()
即可。这意味着大多数魔术都发生在模板中。 Chart.js 是一个客户端 javascript 库,因此我们的app.py
非常少。
结果:
Flask 条形图
使用 Chart.js 和 Flask 创建折线图
要创建折线图,我们只需修改chart.html
模板即可。 更改为:
<meta charset="utf-8">
<title>Chart.js </title>
<!-- import plugin script -->
<script src="static/Chart.min.js"></script>
<h1>Flask Chart.js</h1>
<!-- bar chart canvas element -->
<canvas id="chart" width="600" height="400"></canvas>
<script></p>
<p> // bar chart data<br />
var barData = {<br />
labels : [],<br />
datasets : [<br />
{<br />
fillColor: "rgba(151,187,205,0.2)",<br />
strokeColor: "rgba(151,187,205,1)",<br />
pointColor: "rgba(151,187,205,1)",<br />
pointStrokeColor: "#fff",<br />
pointHighlightFill: "#fff",<br />
pointHighlightStroke: "rgba(151,187,205,1)",<br />
bezierCurve : false,<br />
data : []<br />
}]<br />
}</p>
<p> Chart.defaults.global.animationSteps = 50;<br />
Chart.defaults.global.tooltipYPadding = 16;<br />
Chart.defaults.global.tooltipCornerRadius = 0;<br />
Chart.defaults.global.tooltipTitleFontStyle = "normal";<br />
Chart.defaults.global.tooltipFillColor = "rgba(0,0,0,0.8)";<br />
Chart.defaults.global.animationEasing = "easeOutBounce";<br />
Chart.defaults.global.responsive = false;<br />
Chart.defaults.global.scaleLineColor = "black";<br />
Chart.defaults.global.scaleFontSize = 16;</p>
<p> // get bar chart canvas<br />
var mychart = document.getElementById("chart").getContext("2d");</p>
<p> steps = 10<br />
max = 10<br />
// draw bar chart<br />
var LineChartDemo = new Chart(mychart).Line(barData, {<br />
scaleOverride: true,<br />
scaleSteps: steps,<br />
scaleStepWidth: Math.ceil(max / steps),<br />
scaleStartValue: 0,<br />
scaleShowVerticalLines: true,<br />
scaleShowGridLines : true,<br />
barShowStroke : true,<br />
scaleShowLabels: true,<br />
bezierCurve: false,</p>
<p> });</p>
<p></script>
输出:
Flask 折线图
创建饼图
要创建饼图,我们必须稍加修改应用程序代码。 我们需要 3 个数组:值,标签和颜色。 与 HTML 一样,颜色以十六进制定义。 要在一个循环中对其进行迭代,请压缩它们。
from flask import Flask
from flask import Markup
from flask import Flask
from flask import render_template
app = Flask(__name__)
@app.route("/")
def chart():
labels = ["January","February","March","April","May","June","July","August"]
values = [10,9,8,7,6,4,7,8]
colors = [ "#F7464A", "#46BFBD", "#FDB45C", "#FEDCBA","#ABCDEF", "#DDDDDD", "#ABCABC" ]
return render_template('chart.html', set=zip(values, labels, colors))
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5001)
其次,我们将模板修改为:
<meta charset="utf-8"> <title>Chart.js </title> <!-- import plugin script --> <script src="static/Chart.min.js"></script>
<h1>Flask Chart.js</h1>
<!-- bar chart canvas element --><canvas id="chart" width="600" height="400"></canvas>
<script><br />
var pieData = [<br />
</p>
<p> ];</p>
<p> // get bar chart canvas<br />
var mychart = document.getElementById("chart").getContext("2d");</p>
<p> steps = 10<br />
max = 10<br />
// draw pie chart<br />
new Chart(document.getElementById("chart").getContext("2d")).Pie(pieData);</p>
<p></script>
结果:
Flask 饼图
Python 和 JSON 编码和解码
原文: https://pythonspot.com/json-encoding-and-decoding-with-python/
简介
JSON(JavaScript 对象表示法)在服务器和 Web 应用程序之间经常使用。 JSON 数据的示例:
{
"persons": [
{
"city": "Seattle",
"name": "Brian"
},
{
"city": "Amsterdam",
"name": "David"
}
]
}
json
模块使您可以在 JSON 和 Python 对象之间进行转换。
JSON 转换示例
将 JSON 转换为 Python 对象(字典)
要将 JSON 转换为 Python 字典,请使用以下命令:
import json
json_data = '{"name": "Brian", "city": "Seattle"}'
python_obj = json.loads(json_data)
print python_obj["name"]
print python_obj["city"]
将 JSON 转换为 Python 对象(列表)
JSON 数据可以直接映射到 Python 列表。
import json
array = '{"drinks": ["coffee", "tea", "water"]}'
data = json.loads(array)
for element in data['drinks']:
print element
将 JSON 转换为 Python 对象(浮点)
浮点数可以使用十进制库进行映射。
import json
from decimal import Decimal
jsondata = '{"number": 1.573937639}'
x = json.loads(jsondata, parse_float=Decimal)
print x['number']
将 JSON 转换为 Python 对象(示例)
JSON 数据通常包含多个对象,下面是如何使用该对象的示例:
import json
json_input = '{"persons": [{"name": "Brian", "city": "Seattle"}, {"name": "David", "city": "Amsterdam"} ] }'
try:
decoded = json.loads(json_input)
# Access data
for x in decoded['persons']:
print x['name']
except (ValueError, KeyError, TypeError):
print "JSON format error"
将 Python 对象(字典)转换为 JSON
如果要将 Python 对象转换为 JSON,请使用json.dumps()
方法。
import json
from decimal import Decimal
d = {}
d["Name"] = "Luke"
d["Country"] = "Canada"
print json.dumps(d, ensure_ascii=False)
# result {"Country": "Canada", "Name": "Luke"}
将 JSON 数据转换为 Python 对象
可以使用json.loads()
函数将 JSON 数据转换(反序列化)为 Pyhon 对象。 映射表:
JSON 格式 | Python |
---|---|
对象 | 字典 |
数组 | 列表 |
字符串 | 字符串 |
数字(整数) | 整型 |
数字(实数) | 浮点 |
true |
True |
false |
False |
null |
None |
漂亮的打印
如果要显示 JSON 数据,可以使用json.dumps()
函数。
import json
json_data = '{"name": "Brian", "city": "Seattle"}'
python_obj = json.loads(json_data)
print json.dumps(python_obj, sort_keys=True, indent=4)
更多
使用 Python 和 PyQT 创建 Web 浏览器
原文: https://pythonspot.com/creating-a-webbrowser-with-python-and-pyqt-tutorial/
带有 PyQt4 的 Python 浏览器
在本教程中,我们将使用 Python 构建一个 Web 浏览器。 我们将使用具有 Web 组件的 PyQT 库。 在本教程中,您将学习如何将所有组件链接在一起。 在本教程中,我们将使用默认的渲染引擎,而不是其中一个。
如果您尚未完成我们的 pyqt4 初学者教程,则可以尝试一下。 如果找不到 python-kde4,请更新您的存储库以找到它。 Ubuntu 或 Debian 安装指南。
PyQt 安装
安装所需的软件包:
sudo pip install python-qt4
sudo apt-get install qt4-designer
sudo apt-get install pyqt4-dev-tools
sudo apt-get install python-kde4
使用 PyQt 创建 GUI
从应用程序菜单中启动 qt4-designer。QT 设计器应用程序将出现:
QT 设计器
选择主窗口,然后按创建。 现在,我们打开了设计器窗口。 在窗口上拖动KWebView
组件。 如果组件列表中有QtWebView
。 用它代替。 我们还在顶部添加Line
Edit。 按“文件 > 另存为 >
browser.ui`”。 运行命令:
pyuic4 browser.ui > browser.py
这将生成一个 Python 文件。 从browser.py
文件底部删除from kwebview import KWebView
行。 将KWebView
更改为QtWebView
。 我们想改用QtWebView
。 如果您不愿意进行更改,请从下面获取browser.py
文件。
QWebView
探索
使用以下内容创建一个名为run.py
的文件:
import sys
from browser import BrowserDialog
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import QUrl
from PyQt4.QtWebKit import QWebView
class MyBrowser(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
QWebView.__init__(self)
self.ui = BrowserDialog()
self.ui.setupUi(self)
self.ui.lineEdit.returnPressed.connect(self.loadURL)
def loadURL(self):
url = self.ui.lineEdit.text()
self.ui.qwebview.load(QUrl(url))
self.show()
#self.ui.lineEdit.setText("")
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyBrowser()
myapp.ui.qwebview.load(QUrl('http://www.pythonspot.com'))
myapp.show()
sys.exit(app.exec_())
这段代码将使用browser.py
中定义的 UI 并向其中添加逻辑。
self.ui.lineEdit.returnPressed.connect(self.loadURL)
def loadURL(self):
url = self.ui.lineEdit.text()
self.ui.qwebview.load(QUrl(url))
self.show()
#self.ui.lineEdit.setText("")
第一行定义了回调或事件。 如果有人按下Enter
键(returnPressed
),它将调用函数loadURL
。 确保一旦按下Enter
键,页面就会加载该功能。 如果您正确执行了所有操作,则应该能够使用以下命令运行浏览器:
python run.py
请确保输入完整的网址,例如:http://pythonspot.com 包括 http://
部分。 您的浏览器现在应该启动:
Python 浏览器
如果您的代码未运行,请使用以下代码(或查看不同之处并更改错误之处):
browser.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'browser.ui'
#
# Created: Fri Jan 30 20:49:32 2015
# by: PyQt4 UI code generator 4.10.4
#
# WARNING! All changes made in this file will be lost!
import sys
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import QApplication
from PyQt4.QtCore import QUrl
from PyQt4.QtWebKit import QWebView
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class BrowserDialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName(_fromUtf8("Dialog"))
Dialog.resize(1024, 768)
self.qwebview = QWebView(Dialog)
self.qwebview.setGeometry(QtCore.QRect(0, 50, 1020, 711))
self.qwebview.setObjectName(_fromUtf8("kwebview"))
self.lineEdit = QtGui.QLineEdit(Dialog)
self.lineEdit.setGeometry(QtCore.QRect(10, 20, 1000, 25))
self.lineEdit.setObjectName(_fromUtf8("lineEdit"))
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
Dialog.setWindowTitle(_translate("Browser", "Browser", None))
run.py
import sys
from browser import BrowserDialog
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import QUrl
from PyQt4.QtWebKit import QWebView
class MyBrowser(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
QWebView.__init__(self)
self.ui = BrowserDialog()
self.ui.setupUi(self)
self.ui.lineEdit.returnPressed.connect(self.loadURL)
def loadURL(self):
url = self.ui.lineEdit.text()
self.ui.qwebview.load(QUrl(url))
self.show()
#self.ui.lineEdit.setText("")
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyBrowser()
myapp.ui.qwebview.load(QUrl('http://www.pythonspot.com'))
myapp.show()
sys.exit(app.exec_())
创建一个 gmail 词云
基于 gmail 的词云
我们创建了一个 python 程序,该程序根据您的 gmail 帐户生成一个词云。 输出内容可能看起来像这样,具体取决于您电子邮件的内容。
首先,您将需要一个与 gmail 服务进行交互的小脚本。 我们创建了一个与 gmail 交互的小脚本。 它依赖于已安装的 gmaillib ,您需要进行以下设置:允许“不太安全”的应用程序访问 gmail 服务器: https://www.google.com/settings/security/lesssecureapps
Gmail 示例:
#!/usr/bin/env python
import gmaillib
from collections import Counter
def getMails(cnt,account, start,amount):
emails = account.inbox(start, amount)
for email in emails:
cnt[email.sender_addr] += 1
amountOfMails = 100
cnt = Counter()
username = raw_input("Gmail account: ")
password = raw_input("Password: ")
account = gmaillib.account(username, password)
getMails(cnt,account,0,amountOfMails)
print(cnt)
如果此脚本成功运行,则说明您已安装了几乎所有要求。 您还将需要名为wordcloud
的库。 我们重建系统,以便得到一个包含消息主体的长字符串,并将其作为输入输入到wordcloud
实例中。 可变数量包含要提取的邮件数。 我们已将其设置为 100,但您可以使用get_inbox_count()
将其设置为所有邮件,也可以仅提取上周的所有电子邮件。
最终程序:
#!/usr/bin/env python
import gmaillib
from collections import Counter
from wordcloud import WordCloud
import matplotlib.pyplot as plt
amount = 100
cnt = Counter()
username = raw_input("Gmail account: ")
password = raw_input("Password: ")
account = gmaillib.account(username, password)
emails = account.inbox(0, amount)
data = ""
for email in emails:
data = data + str(email.body)
wordcloud = WordCloud().generate(data)
plt.imshow(wordcloud)
plt.axis("off")
plt.show()
Django 入门
Django 是一个高级 Python Web 框架,它处理了很多 Web 开发的麻烦,因此您可以专注于编写应用程序而无需重新发明轮子。
在本教程中,您将学习如何设置基本的 Django Web 应用程序。
Django 教程
使用以下命令安装 Django:
pip install Django==1.7.1
安装后,为您的应用程序创建目录/django-hello/
。 在此目录中,创建具有以下内容的文件hello.py
:
#!/usr/bin/env python
import sys
from django.conf import settings
from django.conf.urls import patterns
from django.http import HttpResponse
from django.core.management import execute_from_command_line
settings.configure(
DEBUG=True,
SECRET_KEY='asecretkey',
ROOT_URLCONF=sys.modules[__name__],
)
def index(request):
return HttpResponse('Hello, World')
urlpatterns = patterns('',
(r'^hello/$', index),
)
if __name__ == "__main__":
execute_from_command_line(sys.argv)
使用以下命令执行脚本:
python hello.py runserver
HTTP Django 服务器将启动,如果您打开 http://127.0.0.1:8000/hello/
Django Web 框架
Django 代码说明:
最上面的行导入 Django 库:
from django.conf import settings
from django.conf.urls import patterns
from django.http import HttpResponse
from django.core.management import execute_from_command_line
如果打开链接/hello/
,则网络服务器将调用index()
函数。 我们使用以下方式将网址映射到函数:
urlpatterns = patterns('',
(r'^hello/$', index),
)
在 Django 中,我们提供了网址友好的网址。 这意味着您没有以/id=1359835
结尾的 url,而是使用目录作为名称。 最后,我们使用settings.configure
设置一些默认设置。
Django 教程:构建笔记应用程序
原文: https://pythonspot.com/django-tutorial-building-a-note-taking-app/
Django
如果要开始 python Web 开发,可以使用一个名为 Django 的 Web 框架。它被设计为快速,安全和可扩展的。 它带有一个对象关系映射器(ORM),这意味着 Python 中的对象被映射到数据库中的对象。
用 Django 创建的应用程序分为三个独立的层:模型(数据库),视图(外观)和控制器(逻辑),或者简称为模型-视图-控制器(MVC)架构。
设置 Django
首先:
django-admin startproject mysite
这将创建目录mysite
。 打开mysite/mysite/settings.py
。您可以在此处配置所需的数据库:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
从sqlite3
,postgresql_psycopg2
,mysql
或oracle
中选择。 名称是您的数据库的名称。 如果您使用 SQLite,则会自动创建数据库。 对于 MySQL 和 Postgresql,您需要自己创建数据库。 将一个目录转到/mysite/
并运行:
python manage.py runserver
终端应该说:
Performing system checks...
System check identified no issues (0 silenced).
You have unapplied migrations; your app may not work properly until they are applied.
Run 'python manage.py migrate' to apply them.
August 16, 2015 - 14:45:29
Django version 1.7.1, using settings 'myapp.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
[16/Aug/2015 14:45:35] "GET / HTTP/1.1" 200 1759
在网络浏览器中打开 http://127.0.0.1:8000 ,您应该看到:
我们的第一个 Django 应用。
现在我们创建了一个项目,我们创建了一个应用程序。 一个项目可以有许多应用程序。
python manage.py startapp notes
这创建文件:
notes/
init.py
admin.py
migrations/
init.py
models.py
tests.py
views.py
Django 数据库模型
将/mysite/notes/models.py
更改为:
from django.db import models
class Note(models.Model):
text = models.CharField(max_length=120)
created = models.DateTimeField(auto_now_add=True)
打开/mysite/mysite/settings.py
,添加 Web 应用程序:
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'notes'
)
运行:
python manage.py syncdb
这将更新数据库。 然后,我们将/mysite/mysite/admin.py
更新为:
from django.contrib import admin
# Register your models here.
from .models import Note
class NoteAdmin(admin.ModelAdmin):
class Meta:
model = Note
admin.site.register(Note,NoteAdmin)
运行:
python manage.py makemigrations notes
python manage.py migrate
使用以下命令启动服务器:
manage.py runserver
一旦打开管理面板 http://127.0.0.1:8000/admin,笔记将出现在页面上:
Django 管理面板
如果单击笔记,则可以查看所有笔记并添加/删除它们:
Django 数据库管理菜单。
显示数据
我们将所有数据存储在数据库中,现在我们要创建应用程序。 打开/mysite/settings.py
并添加:
#print "base dir path", BASE_DIR
#print os.path.join(os.path.dirname(BASE_DIR), "mysite", "static", "templates")
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(BASE_DIR), "mysite", "static", "templates"),
#'/home/frankbox/python/djangoapp/mysite/static/templates',
)
到文件底部。 这定义了模板的目录(html)。
将/mysite/mysite/urls.py
更改为:
from django.conf.urls import patterns, include, url
from django.contrib import admin
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'mysite.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
url(r'^$', 'notes.views.home', name='home'),
url(r'^admin/', include(admin.site.urls)),
)
最后,创建/mysite/static/templates/
并添加note.html
,这是一个简单的静态 html 文件。
<b>Hello</b>
打开 http://127.0.0.1:8000/ 进行测试。 将note.html
更改为:
<h2>Notes</h2>
<ul>
</ul>
然后打开/mysite/notes/views.py
并更改为:
from django.shortcuts import render, render_to_response, RequestContext
from django.template import RequestContext, loader
from django.http import HttpResponse
from .models import Note
# Create your views here.
def home(request):
notes = Note.objects
template = loader.get_template('note.html')
context = {'notes': notes}
return render(request, 'note.html', context)
#return render_to_response("note.html", notes)
启动浏览器后,您将看到笔记列表:
django 应用
插入数据
虽然有一个列表很不错,但我们想在其中添加一些注释。创建文件/mysite/notes/forms.py
from django import forms
from .models import Note
class NoteForm(forms.ModelForm):
class Meta:
model = Note
将view.py
更改为:
from django.shortcuts import render, render_to_response, RequestContext
from django.template import RequestContext, loader
from django.http import HttpResponse
from .models import Note
from .forms import NoteForm
# Create your views here.
def home(request):
notes = Note.objects
template = loader.get_template('note.html')
form = NoteForm(request.POST or None)
if form.is_valid():
save_it = form.save(commit=False)
save_it.save()
context = {'notes': notes, 'form': form}
return render(request, 'note.html', context)
#return render_to_response("note.html", notes)
最后,我们将note.html
更新为:
<h2>Notes</h2>
<ul>
{% for note in notes.all %}
<li>{ { note.text }}</li>
{% endfor %}</ul>
<form method="POST" action="">{% csrf_token %}
{ { form.as_p }}
<input type="submit">
</form>
运行它,我们有记笔记的应用程序 😃
Djano 记笔记的应用
为应用添加样式
通过修改note.html
,我们可以像其他任何 html/css 网站一样设置其样式。 如果将note.html
更改为:
<link href="http://codepen.io/edbond88/pen/CcgvA.css" media="screen" rel="stylesheet" type="text/css">
<style>
body {<br />
background: rgba(222,222,222,1);<br />
margin: 20px;<br />
}<br />
</style>
<h1>Django Note Taking App</h1>
<form method="POST" action="">{% csrf_token %}
{ { form.as_p }}
<input type="submit" value="Add note">
</form>
你会得到:
Django 笔记记录应用
GUI(图形界面)
GUI 简介
要在 Python 中创建图形界面(GUI),您需要使用库或模块。 至少有三个使用 Python 创建 GUI 的广泛使用的模块:
您可以使用任何这些模块创建图形用户界面(GUI),但它们不具有相同的功能。
GUI 工具包
Tk 提供基本的小部件,例如按钮,菜单,文本和标签。 与 QT4 和 WxPython 相比,它非常有限,但它也是最旧的模块。 它可以在大多数版本的 Mac OS,Linux 和 Windows 上运行。
Tk 中的一个消息框。 用 Tk 制作的 GUI 没有本机外观。
QT4 和 QT5 由 Qt 公司开发。 使用 QT4 或 QT5 制作的图形应用程序可在 Windows,Linux / X11 和 Mac OS X 上运行。它具有大量的小部件,包括选项卡,按钮,项目视图,表视图,进度条,输入字段,日历视图等等。 与 Tk 相比,它有更多可用的小部件。
WxPython 是一个模块,可创建本机 GUI 外观,而与所使用的操作系统无关。 在 Windows 上将其视为 Windows 应用程序,而在 Mac OS 上将其视为 Mac 应用程序。 与 QT4 或 Tk 相比,这可能是一个明显的优势,具体取决于您的用途。 WxWidgets 有许多可用的小部件,例如按钮,菜单,文本,还有更高级的小部件,如htmlview
或树控件。
用 wxPython 创建的窗口。wxPython 在所有操作系统上都有本机外观。
PyQT4 教程
PyQt 被广泛用于开发可在各种操作系统上运行的图形界面。 它是 Python 编程中最受欢迎的 GUI 选择之一。
文章
您可以在下面找到 PyQT 文章的集合。
可以使用 QT Designer 设计应用程序
- QT4 窗口
- QT4 按钮
- QT4 消息框
- QT4 菜单
- QT4 小部件
- QT4 文本框
- QT4 表格
- QT4 标签
- QT4 进度条
- QT4 像素图(图像)
- QT4 打开文件对话框
- QT4:构建应用程序(初学者教程)
- QT4:使用设计器创建 GUI(专业教程)
真实示例
使用 PyQt 的程序示例
- Dropbox
- Ninja IDE
- Veusz
PyQT5
PyQt5 是可用于创建图形用户界面(GUI)的模块。 PyQt5 与 PyQt4 向后不兼容。 您将需要 Python 2.6 或更高版本。 要测试您的 Python 版本,请尝试以下命令之一:
python3 --version python --version
PyQt5 课程
喜欢课程还是想要获得认证?
文章
以下 PyQT5 文章的集合。
- PyQt5 窗口
- PyQt5 状态栏
- PyQt5 按钮
- PyQt5 信号和插槽
- PyQt5 消息框
- PyQt5 文本框
- PyQt5 定位
- PyQt5 菜单
- PyQt5 表
- PyQt5 标签
- PyQt5 水平布局
- PyQt5 网格布局
- PyQt5 输入对话框
- PyQt5 文件对话框
- PyQt5 加载图片
- PyQt5 绘图和像素
- PyQt5 颜色对话框
- PyQt5 颜色
- 拖放
- PyQt5 字体对话框
- PyQt5 matplotlib
- Webkit 浏览器
- PyQt5 完整浏览器
- PyQt5 树状视图
- PyQt5 目录视图
- PyQt5 表单布局
- PyQt5 框布局
Tkinter
标准 GUI(图形用户界面)包被称为 Tkinter。 默认情况下,它包含在 Microsoft Windows 和 Mac OS X 安装的 Python 中。
它有时被称为“Python 世界的次要传统之一”。 Tkinter 绝不是唯一的 GUI 软件包,通常使用替代的 GUI 软件包,例如 PyQT 和 wxPython。
与 PyQT 和 wxPython 相比,Tkinter 仅具有少量的小部件,例如按钮,标签,检查按钮,单选按钮,列表框,滚动框,进度条等。
Tkinter 消息框,Tkinter 的小部件之一。
概述
Tkinter 的简要介绍。
文档
热门书籍:
Tkinter 视频课程:
注意:在 Python 3.x 中,该程序包名为tkinter
。 为 Python 2.x 编写的程序可能正在导入 Tkinter。
wxPython
一个 wxPython 应用程序
在本教程系列中,您将学习使用 wxPython 模块进行图形(GUI)编程的基础。 它是跨平台的:应用程序可以在 Microsoft Windows,Apple OS X 和大多数 Unix 系统上运行。
使用 wxPython 制作的应用程序具有本机系统界面,而无需更改代码。
目录
网络
Python 网络套接字编程教程
原文: https://pythonspot.com/python-network-sockets-programming-tutorial/
在本教程中,您将学习网络编程。您将了解用于万维网,电子邮件和许多其他应用程序的客户端-服务器模型。
客户端服务器(带有电子邮件协议)客户端服务器模型是一个模型,其中有 n 个客户端和一个服务器。 客户端向服务器发出数据请求。 服务器回复收到的那些消息。 客户端可以是任何设备,例如您的计算机或平板电脑。 服务器通常是要 24/7 连接的专用计算机。
套接字服务器代码
此代码将使用套接字启动一个简单的 Web 服务器。 它等待连接,如果接收到连接,它将输出接收到的字节。
#!/usr/bin/env python
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 62
BUFFER_SIZE = 20 # Normally 1024, but we want fast response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connection address:', addr
while 1:
data = conn.recv(BUFFER_SIZE)
if not data: break
print "received data:", data
conn.send(data) # echo
conn.close()
Execute with:
$ python server.py
将在端口 62 处打开 Web 服务器。 在第二个屏幕中,使用 Telnet 打开客户端。 如果将同一台计算机用于客户端和服务器,请使用:
$ telnet 127.0.0.1 62.
如果将另一台计算机用作客户端,请键入该计算机的相应 IP 地址。您可以使用ifconfig
找到它。
您从客户端编写的所有内容都将到达服务器。 服务器将收到的消息发回。下面是一个示例输出(单击放大)
套接字网络客户端:
下面的客户端脚本将消息发送到服务器。 服务器必须正在运行!
#!/usr/bin/env python
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 5005
BUFFER_SIZE = 1024
MESSAGE = "Hello, World!"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(MESSAGE)
data = s.recv(BUFFER_SIZE)
s.close()
print "received data:", data
该客户端仅模仿我们在 Telnet 中所做的行为。
服务器代码的限制
上面的服务器代码只能与一个客户端交互。 如果您尝试连接第二个终端,则根本不会回复新客户端。 要使服务器与多个客户端交互,您需要使用多线程。 我们重建服务器脚本以接受多个客户端连接:
#!/usr/bin/env python
import socket
from threading import Thread
from SocketServer import ThreadingMixIn
class ClientThread(Thread):
def __init__(self,ip,port):
Thread.__init__(self)
self.ip = ip
self.port = port
print "[+] New thread started for "+ip+":"+str(port)
def run(self):
while True:
data = conn.recv(2048)
if not data: break
print "received data:", data
conn.send(data) # echo
TCP_IP = '0.0.0.0'
TCP_PORT = 62
BUFFER_SIZE = 20 # Normally 1024, but we want fast response
tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpsock.bind((TCP_IP, TCP_PORT))
threads = []
while True:
tcpsock.listen(4)
print "Waiting for incoming connections..."
(conn, (ip,port)) = tcpsock.accept()
newthread = ClientThread(ip,port)
newthread.start()
threads.append(newthread)
for t in threads:
t.join()
应用协议
到目前为止,我们只是来回发送了消息。每个消息在应用程序中可以具有特定的含义。这就是所谓的协议。这些消息的含义在发送方和接收方都必须相同。下面的传输层确保接收到消息(TCP)。网络层是 IPv4 协议。我们需要定义的只是应用层。
下面我们修改了服务器以接受简单命令(为简单起见,我们使用非线程服务器)。我们将端口更改为 64。带有协议的服务器代码:
#!/usr/bin/env python
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 64
BUFFER_SIZE = 20 # Normally 1024, but we want fast response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connection address:', addr
while 1:
data = conn.recv(BUFFER_SIZE)
if not data: break
print "received data:", data
#conn.send(data) # echo
if "/version" in data:
conn.send("Demo versionn")
if "/echo" in data:
data = data.replace("/echo","")
conn.send(data + "n")
conn.close()
使用以下命令运行服务器:
sudo python server.py
然后,客户端可以与 telnet 连接(确保选择正确的 IP):
$ telnet 127.0.0.1 64
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
message
/version
Demo version
/echo Repeat this
Repeat this
Requests:人性化的 HTTP
如果要从 Web 服务器请求数据,则在 Python 中执行此操作的传统方法是使用urllib
库。 尽管此库有效,但您可以轻松地构建比构建某些东西所需的复杂性。 还有另一种方法吗?
Requests 是用 Python 编写的 Apache2 许可 HTTP 库。 它由httplib
和urllib3
支持,但为您完成了所有艰苦的工作。
要安装类型:
git clone https://github.com/kennethreitz/requests.git
cd requests
sudo python setup.py install
现在已安装 Requests 库。 我们将在下面列出一些示例:
使用 HTTP / HTTPS 请求获取原始 html
现在,我们可以查询网站:
import requests
r = requests.get('http://pythonspot.com/')
print r.content
保存并运行:
python website.py
它将输出原始 HTML 代码。
使用 Python 下载二进制映像
from PIL import Image
from StringIO import StringIO
import requests
r = requests.get('http://1.bp.blogspot.com/_r-MQun1PKUg/SlnHnaLcw6I/AAAAAAAAA_U$
i = Image.open(StringIO(r.content))
i.show()
使用 python 检索的图像
网站状态代码(网站是否在线?)
import requests
r = requests.get('http://pythonspot.com/')
print r.status_code
这将返回 200(确定)。 可以在此处找到状态代码列表:https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
从 Web 服务器检索 JSON
您可以轻松地从 Web 服务器获取 JSON 对象。
import requests
import requests
r = requests.get('https://api.github.com/events')
print r.json()
使用 Python 的 HTTP 发布请求
from StringIO import StringIO
import requests
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.post("http://httpbin.org/post", data=payload)
print(r.text)
SSL 验证,使用 Python 验证证书
from StringIO import StringIO
import requests
print requests.get('https://github.com', verify=True)
从 HTTP 响应标头中提取数据
对于发送到 HTTP 服务器的每个请求,服务器都会向您发送一些其他数据。 您可以使用以下命令从 HTTP 响应中提取数据:
#!/usr/bin/env python
import requests
r = requests.get('http://pythonspot.com/')
print r.headers
这将以 JSON 格式返回数据。 我们可以将以 JSON 格式编码的数据解析为 Python 字典。
#!/usr/bin/env python
import requests
import json
r = requests.get('http://pythonspot.com/')
jsondata = str(r.headers).replace('\'','"')
headerObj = json.loads(jsondata)
print headerObj['server']
print headerObj['content-length']
print headerObj['content-encoding']
print headerObj['content-type']
print headerObj['date']
print headerObj['x-powered-by']
从 HTML 响应中提取数据
从服务器获取数据后,您可以使用 python 字符串函数或使用库来对其进行解析。 经常使用BeautifulSoup
。 获取页面标题和链接的示例代码:
from bs4 import BeautifulSoup
import requests
# get html data
r = requests.get('http://stackoverflow.com/')
html_doc = r.content
# create a beautifulsoup object
soup = BeautifulSoup(html_doc)
# get title
print soup.title
# print all links
for link in soup.find_all('a'):
print(link.get('href'))
Python 和 HTTP 下载文件
可以使用urllib2
模块从 Web 下载数据(网络资源访问)。 这些数据可以是文件,网站,也可以是您想要 Python 下载的任何数据。 该模块支持 HTTP,HTTPS,FTP 和其他几种协议。
在本文中,您将学习如何使用 Python 从 Web 下载数据。
下载文本
要下载纯文本文件,请使用以下代码:
import urllib2
response = urllib2.urlopen('https://wordpress.org/plugins/about/readme.txt')
data = response.read()
print(data)
我们使用urllib2.urlopen()
方法获得响应对象,其中参数是链接。 使用response.read()
方法调用接收所有文件内容。 调用此命令后,我们将文件数据存储在字符串类型的 Python 变量中。
下载 HTML
这将要求网站提供 html 代码。它将所有内容输出到屏幕。
import urllib2
response = urllib2.urlopen('https://en.wikipedia.org/')
html = response.read()
print html
使用 Python 下载文件
下载文件后,可以非常轻松地将数据保存到磁盘:
import urllib2
response = urllib2.urlopen('https://wordpress.org/plugins/about/readme.txt')
data = response.read()
# Write data to file
filename = "test.txt"
file_ = open(filename, 'w')
file_.write(data)
file_.close()
代码的第一部分将文件内容下载到变量数据中:
import urllib2
response = urllib2.urlopen('https://wordpress.org/plugins/about/readme.txt')
data = response.read()
第二部分将其存储到文件中(此文件不需要具有相同的文件名)
# Write data to file
filename = "test.txt"
file_ = open(filename, 'w')
file_.write(data)
file_.close()
"w"
参数创建文件(如果存在,则覆盖)。 您可以在此处阅读有关写入文件的更多信息。
HTTP:解析 HTML 和 XHTML
在本文中,您将学习如何解析网站的 HTML(超文本标记语言)。 有几个 Python 库可以实现这一目标。 我们将演示一些流行的例子。
Beautiful Soup:用于解析 HTML 和 XML 的 python 包
该库非常流行,甚至可以处理格式错误的标记。 要获取单个div
的内容,可以使用以下代码:
from BeautifulSoup import BeautifulSoup
import urllib2
# get the contents
response = urllib2.urlopen('https://en.wikipedia.org/wiki/Python_(programming_language)')
html = response.read()
parsed_html = BeautifulSoup(html)
print parsed_html.body.find('div', attrs={'class':'toc'})
这将输出 Wikipedia 文章中称为“toc”(目录)的div
中的 HTML 代码。 如果只希望使用原始文本,请使用:
print parsed_html.body.find('div', attrs={'class':'toc'}).text
如果要获取页面标题,则需要从标题部分获取:
print parsed_html.head.find('title').text
要从网站获取所有图像 URL,可以使用以下代码:
from BeautifulSoup import BeautifulSoup
import urllib2
url = 'https://www.arstechnica.com/'
data = urllib2.urlopen(url).read()
soup = BeautifulSoup(data)
links = soup.findAll('img', src=True)
for link in links:
print(link["src"])
要从网页中获取所有 URL,请使用以下命令:
from BeautifulSoup import BeautifulSoup
import urllib2
url = 'https://www.arstechnica.com/'
data = urllib2.urlopen(url).read()
soup = BeautifulSoup(data)
links = soup.findAll('a')
for link in links:
print(link["href"])
PyQuery:一个类似 jquery 的 Python 库
要从标记中提取数据,我们可以使用 PyQuery。 它可以根据您的需要获取实际的文本内容和 html 内容。 要获取标签,请使用调用pq('tag')
。
from pyquery import PyQuery
import urllib2
response = urllib2.urlopen('https://en.wikipedia.org/wiki/Python_(programming_language)')
html = response.read()
pq = PyQuery(html)
tag = pq('div#toc')
# print the text of the div
print tag.text()
# print the html of the div
print tag.html()
要获得标题,只需使用:
tag = pq('title')
HTMLParser
:简单的 HTML 和 XHTML 解析器
该库的用法非常不同。 使用此库,您必须将所有逻辑都放在WebParser
类中。 用法的基本示例如下:
from HTMLParser import HTMLParser
import urllib2
# create parse
class WebParser(HTMLParser):
def handle_starttag(self, tag, attrs):
print "Tag: " + tag
# get the contents
response = urllib2.urlopen('https://en.wikipedia.org/wiki/Python_(programming_language)')
html = response.read()
# instantiate the parser and fed it some HTML
parser = WebParser()
parser.feed(html)
Python 中的 FTP 客户端
本文将从客户端的角度向您展示如何在 Python 中使用文件传输协议(FTP)。 我们使用ftplib
,这是一个实现 FTP 协议的库。 使用 FTP,我们可以通过函数调用创建和访问远程文件。
目录列表
我们可以使用这个小片段列出根目录:
import ftplib
ftp = ftplib.FTP("ftp.nluug.nl")
ftp.login("anonymous", "ftplib-example-1")
data = []
ftp.dir(data.append)
ftp.quit()
for line in data:
print "-", line
这将输出目录内容。 以简单的控制台样式输出。 如果要显示特定目录,则必须在连接ftp.cwd('/')
函数后更改目录,其中参数是您要更改的目录。
import ftplib
ftp = ftplib.FTP("ftp.nluug.nl")
ftp.login("anonymous", "ftplib-example-1")
data = []
ftp.cwd('/pub/') # change directory to /pub/
ftp.dir(data.append)
ftp.quit()
for line in data:
print "-", line
下载文件
要下载文件,我们使用retrbinary()
函数。 下面的例子:
import ftplib
import sys
def getFile(ftp, filename):
try:
ftp.retrbinary("RETR " + filename ,open(filename, 'wb').write)
except:
print "Error"
ftp = ftplib.FTP("ftp.nluug.nl")
ftp.login("anonymous", "ftplib-example-1")
ftp.cwd('/pub/') # change directory to /pub/
getFile(ftp,'README.nluug')
ftp.quit()
上传文件
我们可以使用storlines()
命令上传文件。 这将在主目录中上传文件README.nluug
。 如果要在另一个目录中上传,请与cwd()
函数结合使用。
import ftplib
import os
def upload(ftp, file):
ext = os.path.splitext(file)[1]
if ext in (".txt", ".htm", ".html"):
ftp.storlines("STOR " + file, open(file))
else:
ftp.storbinary("STOR " + file, open(file, "rb"), 1024)
ftp = ftplib.FTP("127.0.0.1")
ftp.login("username", "password")
upload(ftp, "README.nluug")
其他函数
有关其他函数,请参考官方库文档。
构建一个 IRC(ro)机器人
有 IRC(互联网中继聊天)的大量(ro)机器人。 那么,如何仅仅为了好玩而开始在 Python 中构建和构建一个?
您将需要一个与 IRC 服务器连接并像传统 IRC 客户端一样运行的程序。IRC 服务器从不要求进行任何复杂的人工验证,例如解决验证码,这就是为什么我们可以简单地使用脚本进行连接的原因。该脚本本身将使用网络套接字,一个库,该库通常用于以多种编程语言(包括 Python 和 C / C++)提供网络交互。
IRC 和 Python
要与 IRC 服务器通信,您需要使用 IRC 协议。 IRC 协议具有不同的消息,例如 PRIVMSG,USER,NICK 和 JOIN。 如果您好奇,可以阅读整个协议。 但是遵循本教程可能会更简单;仅需执行几个步骤即可完成身份验证:
IRC 协议是 IP 协议之上的一层。 要创建套接字,请使用以下命令:
irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.AF_INET
通知库使用网络协议 IPv4。第二个参数告诉库使用流套接字,该套接字通常在 TCP 协议上实现。(IRC 通过 TCP/IP 进行工作)。 然后,我们必须使用以下命令对服务器进行身份验证:
USER botname botname botname: phrase
NICK botname
JOIN #channel
有时IDENT
命令也是必要的。 总结一下,我们得到了这个类(另存为irc.py
):
import socket
import sys
class IRC:
irc = socket.socket()
def __init__(self):
self.irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def send(self, chan, msg):
self.irc.send("PRIVMSG " + chan + " " + msg + "n")
def connect(self, server, channel, botnick):
#defines the socket
print "connecting to:"+server
self.irc.connect((server, 6667)) #connects to the server
self.irc.send("USER " + botnick + " " + botnick +" " + botnick + " :This is a fun bot!n") #user authentication
self.irc.send("NICK " + botnick + "n")
self.irc.send("JOIN " + channel + "n") #join the chan
def get_text(self):
text=self.irc.recv(2040) #receive the text
if text.find('PING') != -1:
self.irc.send('PONG ' + text.split() [1] + 'rn')
return text
现在我们有了网络连接类,我们可以将其用作实例。 为了说明的目的,我们将使我们的(机器人)机器人保持简单。 如果漫游器在其驻留的通道中收到消息"hello"
,则它将回复"Hello!"
。
from irc import *
import os
import random
channel = "#testit"
server = "irc.freenode.net"
nickname = "reddity"
irc = IRC()
irc.connect(server, channel, nickname)
while 1:
text = irc.get_text()
print text
if "PRIVMSG" in text and channel in text and "hello" in text:
irc.send(channel, "Hello!")
将其另存为bot.py
并使用python bot.py
运行。使用传统的 irc 客户端(mirc,hexchat,irsii)连接到该频道,并观察实验是否成功! 现在,您可以使用可以想象的任何出色功能对其进行扩展。
读取电子邮件,pop3
在本教程中,您将学习如何使用poplib
模块来接收电子邮件。 邮件服务器需要支持 pop3,但是大多数邮件服务器都支持。邮局协议(POP3)仅用于接收邮件,发送时需要 SMTP 协议。
简化邮件服务器
元数据
每封电子邮件将包含许多变量,但是这些是最重要的变量:
特征 | 描述 |
---|---|
消息 ID | 唯一标识符 |
从 | 电子邮件来自哪里? |
至 | 电子邮件发送到哪里了? |
日期 | 日期 |
主题 | 电子邮件主题。 |
读取电子邮件示例
您可以使用邮局协议(协议)直接从邮件服务器请求消息。您不必担心内部协议,因为您可以使用poplib
模块。
使用以下方法连接服务器并进行身份验证:
# connect to server
server = poplib.POP3(SERVER)
# login
server.user(USER)
server.pass_(PASSWORD)
下面的程序从服务器获取 10 封电子邮件,包括邮件头
import poplib
import string, random
import StringIO, rfc822
def readMail():
SERVER = "YOUR MAIL SERVER"
USER = "YOUR USERNAME [email protected]COM"
PASSWORD = "YOUR PASSWORD"
# connect to server
server = poplib.POP3(SERVER)
# login
server.user(USER)
server.pass_(PASSWORD)
# list items on server
resp, items, octets = server.list()
for i in range(0,10):
id, size = string.split(items[i])
resp, text, octets = server.retr(id)
text = string.join(text, "\n")
file = StringIO.StringIO(text)
message = rfc822.Message(file)
for k, v in message.items():
print k, "=", v
readMail()
从网页中提取链接(BeautifulSoup
)
原文: https://pythonspot.com/extract-links-from-webpage-beautifulsoup/
Web 抓取是从网站提取数据的技术。
模块BeautifulSoup
设计用于网页抓取。BeautifulSoup
模块可以处理 HTML 和 XML。 它提供了用于搜索,导航和修改分析树的简单方法。
从网站获取链接
下面的示例在网页上打印所有链接:
from BeautifulSoup import BeautifulSoup
import urllib2
import re
html_page = urllib2.urlopen("https://arstechnica.com")
soup = BeautifulSoup(html_page)
for link in soup.findAll('a', attrs={'href': re.compile("^http://")}):
print link.get('href')
它下载带有行的原始 html 代码:
html_page = urllib2.urlopen("https://arstechnica.com")
创建了BeautifulSoup
对象,我们使用该对象查找所有链接:
soup = BeautifulSoup(html_page)
for link in soup.findAll('a', attrs={'href': re.compile("^http://")}):
print link.get('href')
将网站链接提取到数组中
要将链接存储在数组中,可以使用:
from BeautifulSoup import BeautifulSoup
import urllib2
import re
html_page = urllib2.urlopen("https://arstechnica.com")
soup = BeautifulSoup(html_page)
links = []
for link in soup.findAll('a', attrs={'href': re.compile("^http://")}):
links.append(link.get('href'))
print(links)
从网页提取链接的函数
如果您反复提取链接,则可以使用以下函数:
from BeautifulSoup import BeautifulSoup
import urllib2
import re
def getLinks(url):
html_page = urllib2.urlopen(url)
soup = BeautifulSoup(html_page)
links = []
for link in soup.findAll('a', attrs={'href': re.compile("^http://")}):
links.append(link.get('href'))
return links
print( getLinks("https://arstechnica.com") )
绘图
Matplotlib 折线图
可以使用 Matplotlib plot()
函数创建折线图。 尽管我们可以绘制一条线,但我们不仅限于此。 我们可以显式定义网格,x
和y
轴比例以及标签,标题和显示选项。
折线图示例
下面的示例将创建一个折线图。
from pylab import *
t = arange(0.0, 2.0, 0.01)
s = sin(2.5*pi*t)
plot(t, s)
xlabel('time (s)')
ylabel('voltage (mV)')
title('Sine Wave')
grid(True)
show()
输出:
Python Matplotlib 折线图
这些行:
from pylab import *
t = arange(0.0, 2.0, 0.01)
s = sin(2.5*pi*t)
只需定义要绘制的数据。
from pylab import *
t = arange(0.0, 2.0, 0.01)
s = sin(2.5*pi*t)
plot(t, s)
show()
绘制图表。 其他语句非常简单:语句xlabel()
设置x
轴文本,ylabel()
设置y
轴文本,title()
设置图表标题,grid(True)
只是打开网格。
如果要将图保存到磁盘,请调用以下语句:
savefig("line_chart.png")
绘制自定义折线图
如果要使用数组(列表)进行绘制,则可以执行以下脚本:
from pylab import *
t = arange(0.0, 20.0, 1)
s = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
plot(t, s)
xlabel('Item (s)')
ylabel('Value')
title('Python Line Chart: Plotting numbers')
grid(True)
show()
该声明:
t = arange(0.0, 20.0, 1)
定义从 0 开始,以 1 为步长绘制 20 个项目(数组的长度)。
输出:
来自列表的 Python 折线图
多个图
如果要在一张图表中绘制多条线,只需多次调用plot()
函数。 一个例子:
from pylab import *
t = arange(0.0, 20.0, 1)
s = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
s2 = [4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]
plot(t, s)
plot(t, s2)
xlabel('Item (s)')
ylabel('Value')
title('Python Line Chart: Plotting numbers')
grid(True)
show()
输出:
python 多个折线图
如果要在同一窗口中的不同视图中绘制它们,可以使用以下方法:
import matplotlib.pyplot as plt
from pylab import *
t = arange(0.0, 20.0, 1)
s = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
s2 = [4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]
plt.subplot(2, 1, 1)
plt.plot(t, s)
plt.ylabel('Value')
plt.title('First chart')
plt.grid(True)
plt.subplot(2, 1, 2)
plt.plot(t, s2)
plt.xlabel('Item (s)')
plt.ylabel('Value')
plt.title('Second chart')
plt.grid(True)
plt.show()
输出:
Python 子图
这里的plt.subplot()
语句是关键。subplot()
命令指定数字,数字和数字。
设置图的样式
如果要粗线或设置颜色,请使用:
plot(t, s, color="red", linewidth=2.5, linestyle="-")
Matplotlib 直方图
Matplotlib 可用于创建直方图。直方图在垂直轴上显示频率,水平轴是另一个维度。通常它具有箱,其中每个箱具有最小值和最大值。 每个箱的频率也介于x
和无穷大之间。
Matplotlib 直方图示例
下面显示了最小的 Matplotlib 直方图:
import numpy as np
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
x = [21,22,23,4,5,6,77,8,9,10,31,32,33,34,35,36,37,18,49,50,100]
num_bins = 5
n, bins, patches = plt.hist(x, num_bins, facecolor='blue', alpha=0.5)
plt.show()
输出:
Python 直方图
完整的 matplotlib 直方图
许多东西都可以添加到直方图中,例如拟合线,标签等。 下面的代码创建了更高级的直方图。
#!/usr/bin/env python
import numpy as np
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
# example data
mu = 100 # mean of distribution
sigma = 15 # standard deviation of distribution
x = mu + sigma * np.random.randn(10000)
num_bins = 20
# the histogram of the data
n, bins, patches = plt.hist(x, num_bins, normed=1, facecolor='blue', alpha=0.5)
# add a 'best fit' line
y = mlab.normpdf(bins, mu, sigma)
plt.plot(bins, y, 'r--')
plt.xlabel('Smarts')
plt.ylabel('Probability')
plt.title(r'Histogram of IQ: $\mu=100$, $\sigma=15$')
# Tweak spacing to prevent clipping of ylabel
plt.subplots_adjust(left=0.15)
plt.show()
输出:
Python 直方图
Matplotlib 条形图
Matplotlib 可用于创建条形图。 您可能喜欢 Matplotlib 图库。
条形图代码
下面的代码创建一个条形图:
import matplotlib.pyplot as plt; plt.rcdefaults()
import numpy as np
import matplotlib.pyplot as plt
objects = ('Python', 'C++', 'Java', 'Perl', 'Scala', 'Lisp')
y_pos = np.arange(len(objects))
performance = [10,8,6,4,2,1]
plt.bar(y_pos, performance, align='center', alpha=0.5)
plt.xticks(y_pos, objects)
plt.ylabel('Usage')
plt.title('Programming language usage')
plt.show()
输出:
Python 条形图
Matplotlib 图表可以是水平的,以创建水平条形图:
import matplotlib.pyplot as plt; plt.rcdefaults()
import numpy as np
import matplotlib.pyplot as plt
objects = ('Python', 'C++', 'Java', 'Perl', 'Scala', 'Lisp')
y_pos = np.arange(len(objects))
performance = [10,8,6,4,2,1]
plt.barh(y_pos, performance, align='center', alpha=0.5)
plt.yticks(y_pos, objects)
plt.xlabel('Usage')
plt.title('Programming language usage')
plt.show()
输出:
水平条形图
有关条形图的更多信息
您可以使用以下 Matplotlib 代码比较两个数据系列:
import numpy as np
import matplotlib.pyplot as plt
# data to plot
n_groups = 4
means_frank = (90, 55, 40, 65)
means_guido = (85, 62, 54, 20)
# create plot
fig, ax = plt.subplots()
index = np.arange(n_groups)
bar_width = 0.35
opacity = 0.8
rects1 = plt.bar(index, means_frank, bar_width,
alpha=opacity,
color='b',
label='Frank')
rects2 = plt.bar(index + bar_width, means_guido, bar_width,
alpha=opacity,
color='g',
label='Guido')
plt.xlabel('Person')
plt.ylabel('Scores')
plt.title('Scores by person')
plt.xticks(index + bar_width, ('A', 'B', 'C', 'D'))
plt.legend()
plt.tight_layout()
plt.show()
输出:
Python 条形图比较
Matplotlib 饼图
Matplotlib 使用pie()
函数支持饼图。 您可能喜欢 Matplotlib 图库。
Matplotlib 饼图
下面的代码创建一个饼图:
import matplotlib.pyplot as plt
# Data to plot
labels = 'Python', 'C++', 'Ruby', 'Java'
sizes = [215, 130, 245, 210]
colors = ['gold', 'yellowgreen', 'lightcoral', 'lightskyblue']
explode = (0.1, 0, 0, 0) # explode 1st slice
# Plot
plt.pie(sizes, explode=explode, labels=labels, colors=colors,
autopct='%1.1f%%', shadow=True, startangle=140)
plt.axis('equal')
plt.show()
输出:
python 饼图
要添加图例,请使用plt.legend()
函数:
import matplotlib.pyplot as plt
labels = ['Cookies', 'Jellybean', 'Milkshake', 'Cheesecake']
sizes = [38.4, 40.6, 20.7, 10.3]
colors = ['yellowgreen', 'gold', 'lightskyblue', 'lightcoral']
patches, texts = plt.pie(sizes, colors=colors, shadow=True, startangle=90)
plt.legend(patches, labels, loc="best")
plt.axis('equal')
plt.tight_layout()
plt.show()
输出:
python 饼图
Matplotlib 图例
Matplotlib 对图例具有本机支持。 图例可以放置在各个位置:图例可以放置在图表的内部或外部,并且可以移动位置。
legend()
方法将图例添加到绘图中。 在本文中,我们将向您展示一些使用 matplotlib 的图例示例。
Matplotlib 内部图例
要将图例放置在内部,只需调用legend()
:
import matplotlib.pyplot as plt
import numpy as np
y = [2,4,6,8,10,12,14,16,18,20]
y2 = [10,11,12,13,14,15,16,17,18,19]
x = np.arange(10)
fig = plt.figure()
ax = plt.subplot(111)
ax.plot(x, y, label='$y = numbers')
ax.plot(x, y2, label='$y2 = other numbers')
plt.title('Legend inside')
ax.legend()
plt.show()
Matplotlib 内部图例
Matplotlib 底部图例
要将图例置于底部,请将legend()
调用更改为:
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05), shadow=True, ncol=2)
考虑到我们设置了列数ncol = 2
并设置了阴影。
完整的代码为:
import matplotlib.pyplot as plt
import numpy as np
y = [2,4,6,8,10,12,14,16,18,20]
y2 = [10,11,12,13,14,15,16,17,18,19]
x = np.arange(10)
fig = plt.figure()
ax = plt.subplot(111)
ax.plot(x, y, label='$y = numbers')
ax.plot(x, y2, label='$y2 = other numbers')
plt.title('Legend inside')
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05), shadow=True, ncol=2)
plt.show()
放在底部的图例
Matplotlib 顶部图例
要将图例放在顶部,请更改bbox_to_anchor
值:
ax.legend(loc='upper center', bbox_to_anchor=(0.5, 1.00), shadow=True, ncol=2)
代码:
import matplotlib.pyplot as plt
import numpy as np
y = [2,4,6,8,10,12,14,16,18,20]
y2 = [10,11,12,13,14,15,16,17,18,19]
x = np.arange(10)
fig = plt.figure()
ax = plt.subplot(111)
ax.plot(x, y, label='$y = numbers')
ax.plot(x, y2, label='$y2 = other numbers')
plt.title('Legend inside')
ax.legend(loc='upper center', bbox_to_anchor=(0.5, 1.00), shadow=True, ncol=2)
plt.show()
顶部图例
外部右侧图例
我们可以通过调整框的大小并相对于图例放置图例来在外部放置图例:
chartBox = ax.get_position()
ax.set_position([chartBox.x0, chartBox.y0, chartBox.width*0.6, chartBox.height])
ax.legend(loc='upper center', bbox_to_anchor=(1.45, 0.8), shadow=True, ncol=1)
代码:
import matplotlib.pyplot as plt
import numpy as np
y = [2,4,6,8,10,12,14,16,18,20]
y2 = [10,11,12,13,14,15,16,17,18,19]
x = np.arange(10)
fig = plt.figure()
ax = plt.subplot(111)
ax.plot(x, y, label='$y = numbers')
ax.plot(x, y2, label='$y2 = other numbers')
plt.title('Legend outside')
chartBox = ax.get_position()
ax.set_position([chartBox.x0, chartBox.y0, chartBox.width*0.6, chartBox.height])
ax.legend(loc='upper center', bbox_to_anchor=(1.45, 0.8), shadow=True, ncol=1)
plt.show()
Matplotlib 外部图例
Matplotlib 将图形保存到图像文件
原文: https://pythonspot.com/matplotlib-save-figure-to-image-file/
保存图形
Matplotlib可以使用savefig()
将图直接保存到文件中。
该方法可以像这样使用:
fig.savefig('plot.png')
完整的例子:
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
y = [2,4,6,8,10,12,14,16,18,20]
x = np.arange(10)
fig = plt.figure()
ax = plt.subplot(111)
ax.plot(x, y, label='$y = numbers')
plt.title('Legend inside')
ax.legend()
#plt.show()
fig.savefig('plot.png')
要更改格式,只需更改扩展名,如下所示:
fig.savefig('plot.pdf')
您可以使用打开文件
display plot.png
或在图片或 pdf 查看器中打开它,
保存到 pdf 的图
Matplotlib 更新绘图
更新 matplotlib 绘图非常简单。 创建数据,绘图并循环更新。
启用交互模式至关重要:plt.ion()
。 这控制是否通过每个draw()
命令重绘图形。 如果它为False
(默认值),则该图不会自动更新。
更新绘图示例
复制下面的代码以测试交互式绘图。
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10*np.pi, 100)
y = np.sin(x)
plt.ion()
fig = plt.figure()
ax = fig.add_subplot(111)
line1, = ax.plot(x, y, 'b-')
for phase in np.linspace(0, 10*np.pi, 100):
line1.set_ydata(np.sin(0.5 * x + phase))
fig.canvas.draw()
Capture of a frame of the program above
说明
我们使用以下方法创建要绘制的数据:
x = np.linspace(0, 10*np.pi, 100)
y = np.sin(x)
使用以下命令打开交互模式:
plt.ion()
配置图("b-"
表示蓝线):
fig = plt.figure()
ax = fig.add_subplot(111)
line1, = ax.plot(x, y, 'b-')
最后循环更新:
for phase in np.linspace(0, 10*np.pi, 100):
line1.set_ydata(np.sin(0.5 * x + phase))
fig.canvas.draw()
使用 matplotlib 绘制时间
Matplotlib 支持在水平(x
)轴上带有时间的图。 数据值将放在垂直(y
)轴上。 在本文中,我们将通过一些示例进行演示。
需要使用 Python datetime
模块(标准模块)。
绘制时间
您可以使用时间戳绘制时间:
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import datetime
# create data
y = [ 2,4,6,8,10,12,14,16,18,20 ]
x = [datetime.datetime.now() + datetime.timedelta(hours=i) for i in range(len(y))]
# plot
plt.plot(x,y)
plt.gcf().autofmt_xdate()
plt.show()
如果要更改间隔,请使用以下几行之一:
# minutes
x = [datetime.datetime.now() + datetime.timedelta(minutes=i) for i in range(len(y))]
从特定小时/分钟开始的时间图
要从特定日期开始,请使用datetime.datetime(year, month, day, hour, minute)
创建新的时间戳。
完整示例:
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import datetime
# create data
customdate = datetime.datetime(2016, 1, 1, 13, 30)
y = [ 2,4,6,8,10,12,14,16,18,20 ]
x = [customdate + datetime.timedelta(hours=i) for i in range(len(y))]
# plot
plt.plot(x,y)
plt.gcf().autofmt_xdate()
plt.show()
高级
正则表达式
正则表达式本质上是嵌入在 Python 中的一种高度专业化的编程语言,它使您能够为想要匹配的可能字符串集指定规则。
在 Python 中,您需要re
模块来使用正则表达式。 语法概述在此页面的底部。
匹配函数
匹配函数定义为:
re.match(pattern, string)
参数为:
参数 | 描述 |
---|---|
pattern |
正则表达式 |
string |
输入字符串 |
如果要将字符串与正好为五个的数字序列匹配,可以使用以下代码:
#!/usr/bin/python
import re
input = raw_input("Enter an input string:")
m = re.match('\d{5}\Z',input)
if m:
print("True")
else:
print("False")
输出示例:
电子邮件验证正则表达式
我们可以使用相同的函数来验证电子邮件地址。 语法规则在re.compile
和语法表中可见。
字符串 | 匹配 |
---|---|
12345 |
真 |
12358 |
真 |
55555 |
真 |
123 |
假 |
123K5 |
假 |
5555555 |
假 |
#!/usr/bin/python
import re
input = raw_input("Enter an input string:")
m = re.match('[^@][email protected][^@]+\.[^@]+',input)
if m:
print("True")
else:
print("False")
搜索函数
搜索函数定义为:
re.search(pattern, string)
参数为:
参数 | 描述 |
---|---|
pattern |
正则表达式,定义要搜索的字符串 |
string |
搜索空间 |
要搜索电子邮件地址是否在字符串中:
#!/usr/bin/python
import re
input = "Contact me by [email protected] or at the office."
m = re.search('[^@][email protected][^@]+\.[^@]+',input)
if m:
print("String found.")
else:
print("Nothing found.")
正则表达式示例
正则表达式的一些示例:
正则表达式语法
正则表达式语法概述:
示例 | 正则表达式 |
---|---|
IP 地址 | `(([2][5][0-5].) |
电子邮件 | [^@]+@[^@]+\.[^@]+ |
日期MM/DD/YY |
(\d+/\d+/\d+) |
整数(正) | (?<![-.])\b[0-9]+\b(?!\.[0-9]) |
整数 | [+-]?(?<!\.)\b[0-9]+\b(?!\.[0-9]) |
浮点 | `(?<=>)\d+.\d+ |
十六进制 | \s–([0-9a-fA-F]+)(?:–)?\s |
正则表达式 | 描述 |
---|---|
\d |
匹配任何十进制数字; 这相当于类[0-9] |
\D |
匹配任何非数字字符; 这等效于类[^0-9] 。 |
\s |
匹配任何空白字符; 这等效于类[ \t\n\r\f\v] 。 |
\S |
匹配任何非空白字符; 这等效于类[^ \t\n\r\f\v] 。 |
\w |
匹配任何字母数字字符; 这等效于类[a-zA-Z0-9_] 。 |
\W |
匹配任何非字母数字字符; 这等效于类[^a-zA-Z0-9_] 。 |
\Z |
仅在字符串末尾匹配 |
[..] |
匹配括号中的单个字符 |
[^..] |
匹配任何不在方括号中的单个字符 |
. |
匹配换行符以外的任何字符 |
` | 正则表达式 |
--- | --- |
\d |
匹配任何十进制数字; 这相当于类[0-9] |
\D |
匹配任何非数字字符; 这等效于类[^0-9] 。 |
\s |
匹配任何空白字符; 这等效于类[ \t\n\r\f\v] 。 |
\S |
匹配任何非空白字符; 这等效于类[^ \t\n\r\f\v] 。 |
\w |
匹配任何字母数字字符; 这等效于类[a-zA-Z0-9_] 。 |
\W |
匹配任何非字母数字字符; 这等效于类[^a-zA-Z0-9_] 。 |
\Z |
仅在字符串末尾匹配 |
[..] |
匹配括号中的单个字符 |
[^..] |
匹配任何不在方括号中的单个字符 |
. |
匹配换行符以外的任何字符 |
匹配字符串的结尾 | |
* |
匹配 0 个或更多重复 |
+ |
1 次或多次重复 |
{m} |
之前 RE 的确切 m 个副本应匹配。 |
| |
匹配 A 或 B。 |
? |
先前 RE 的 0 或 1 次重复 |
[a-z] |
任何小写字符 |
[A-Z] |
任何大写字符 |
[a-zA-Z] |
任何字符 |
[0-9] |
任何数字 |
用 Python 构建量子计算应用程序简介
原文: https://pythonspot.com/an-introduction-to-building-quantum-computing-applications-with-python/
因此,我们想使用 Python 创建一个量子应用程序,但是由于我们不拥有任何量子计算机,因此我们首先需要拥有一个模拟器。 模拟将不会具有与实际量子计算机相同的性能,但是我们将能够运行应用程序。 我们可以从以下三个模拟器中进行选择:PyQu,QuTip 和 Qitensor。 我们决定选择 QuTip,因为它具有非常大的代码库并且具有最新更改。自 2010 年以来,PyQu 尚未更新,而 Qtensor 至今已有约一年的时间。
安装
在本教程中,我们使用 Unix 计算机,但是使用其他任何操作系统都应该可以。 使用以下方法安装:
sudo add-apt-repository ppa:jrjohansson/qutip-releases
sudo apt-get update
sudo apt-get install python-qutip
然后,我们从命令行启动 Python 并键入下面列出的命令(>>>
)。
$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:38)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from qutip import *
>>> about()
QuTiP: Quantum Toolbox in Python
Copyright (c) 2011 and later.
Paul D. Nation & Robert J. Johansson
QuTiP Version: 3.1.0
Numpy Version: 1.8.2
Scipy Version: 0.13.3
Cython Version: 0.20.1post0
Matplotlib Version: 1.3.1
Fortran mcsolver: True
scikits.umfpack: False
Python Version: 2.7.6
Platform Info: Linux (i686)
Installation path: /usr/lib/python2.7/dist-packages/qutip
这表明 Qutip 已正确安装。
量子数据结构
在量子系统中,我们需要一个能够封装量子运算符和 ket/bra 向量的属性的数据结构,为此我们使用Qobj
数据结构。 换句话说,为了有效地模拟量子应用,我们需要使用适当的数据结构。 考虑下面的示例:
#!/usr/bin/env python
from qutip import *
from scipy import *
r = rand(4, 4)
print Qobj(r)
并执行:
python quantum.py
这将输出量子对象:
Quantum object: dims = [[4], [4]], shape = [4, 4], type = oper, isherm = False
Qobj data =
[[ 0.25529374 0.75548592 0.85680266 0.1438253
[ 0.75070138 0.68628867 0.97435624 0.77396516]
[ 0.69819458 0.81714756 0.2604015 0.69051901]
[ 0.0898242 0.05292657 0.49134431 0.4433644 ]]
如果要自己指定用户输入,则可以使用:
#!/usr/bin/env python
from qutip import *
from scipy import *
x = array([[1],[2],[3],[4],[5]])
q = Qobj(x)
print q
这个量子对象将简单地保存您的用户给定的数据:
Quantum object: dims = [[5], [1]], shape = [5, 1], type = ket
Qobj data =
[[ 1.]
[ 2.]
[ 3.]
[ 4.]
[ 5.]]
量子态和运算符
量子系统不是简单的两级系统,它具有多个状态。 QuTip 包括此处列出的一些预定义状态和量子运算符。
量子位和运算符
我们创建一个量子位来保存数据。 量子位是经典位的量子模拟。 与传统位不同,量子位可以同时处于两种状态的叠加,这是量子计算的基础。 下面的代码将创建一个量子位:
#!/usr/bin/env python
from qutip import *
from scipy import *
spin = basis(2, 0)
print spin
现在,您可以在量子位上应用量子系统运算符:
#!/usr/bin/env python
from qutip import *
from scipy import *
spin = basis(2, 0)
print sigmam() * spin
print sigmap() * spin
组合量子位
为了描述两个耦合量子位的状态,我们需要为每个系统组件获取状态向量的张量积。 让我们尝试一下:
#!/usr/bin/env python
from qutip import *
from scipy import *
q1 = basis(2, 0)
q2 = basis(2,0)
print q1
print q2
print tensor(q1,q2)
我们将得到的输出是:
Quantum object: dims = [[2], [1]], shape = [2, 1], type = ket
Qobj data =
[[ 1.]
[ 0.]]
Quantum object: dims = [[2], [1]], shape = [2, 1], type = ket
Qobj data =
[[ 1.]
[ 0.]]
Quantum object: dims = [[2, 2], [1, 1]], shape = [4, 1], type = ket
Qobj data =
[[ 1.]
[ 0.]
[ 0.]
[ 0.]]
接下来是什么?
我们使用此简单介绍构建了一些非常简单的量子应用程序。 也许您想创建一个实际有用的应用程序,如果可以的话,您可以研究更多有关量子计算的知识,并在 http://qutip.org/docs/2.2.0/index.html 上完成本教程。
其他
使用 Python 创建 Chrome 插件
原文: https://pythonspot.com/create-a-chrome-plugin-with-python/
使用 Python 创建的 Google Chrome 扩展程序(无服务器,方法 B)。
Google Chrome 插件使用 HTML,JavaScript 和 CSS 编写。 如果您以前从未编写过 Chrome 插件,我推荐 chrome 扩展程序文档。
您可以使用 Python 代替 JavaScript,在本教程中,我们将向您展示如何做到这一点。
很忙?从此站点下载代码:
下载扩展代码(并向下滚动到方法 B)
创建一个 Google Chrome 插件
首先,我们必须创建一个清单文件:manifest.json
。
{
"manifest_version": 2,
"name": "Python Chrome Plugin",
"description": "This extension runs Python code.",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"activeTab",
"https://ajax.googleapis.com/"
]
}
创建一个名为popup.html
的文件
<!doctype html>
<!--
This page is shown when the extension button is clicked, because the
"browser_action" field in manifest.json contains the "default_popup" key with
value "popup.html".
-->
<html>
<head>
<title>Getting Started Extension's Popup</title>
<style>
body {
font-family: "Segoe UI", "Lucida Grande", Tahoma, sans-serif;
font-size: 100%;
}
#status {
/* avoid an excessively wide status text */
white-space: pre;
text-overflow: ellipsis;
overflow: hidden;
max-width: 400px;
}
</style>
<!--
- JavaScript and HTML must be in separate files: see our Content Security
- Policy documentation[1] for details and explanation.
-
- [1]: https://developer.chrome.com/extensions/contentSecurityPolicy
-->
<script src="popup.js"></script>
</head>
<body>
<div id="status"></div>
<img id="image-result" hidden>
</body>
</html>
最后得到一个图标,并将其另存为icon.png
。 打开 chrome://extensions,然后按开发人员模式。 按“加载解压的扩展”,选择目录,然后按 OK。
将 Python 添加到 Chrome 扩展程序
我们有两个选项可将 Python 添加到 chrome 扩展中:
-
方法 A:将 Brython 包含在
iframe
中(需要服务器) -
方法 B:使用 Rapydscript(最佳,无服务器,纯扩展)将 Python 编译为 Javascript。
方法 A:iframe
中的 Python(Brython)
既然您已经掌握了基本知识,我们就可以将 Python 添加到代码中。要在浏览器中运行 Python,您可以使用多个选项,包括 Brython 和 emcascripten。我们决定尝试 Brython。 我们将从服务器运行 Brython 脚本。将popup.html
更改为:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta charset="iso-8859-1">
<style>
body {
margin: 0 !important;
padding: 0 !important;
width: 800;
}
#frame {
overflow: hidden;
width:790;
height:324;
}
</style>
</head>
<body onLoad="">
<iframe src=http://brython.info/console.html id="frame" seamless="seamless" scrolling="no"></iframe>
</body>
</html>
重新启动插件后,您的 Google Chrome 浏览器中将包含一个 Python(Brython)解释器。
Google Chrome 中的 Python
运行您自己的脚本
要运行您自己的脚本,只需更改popup.html
框架内的 url:
<iframe src="BRYTHON SCRIPT URL" id="frame" seamless="seamless" scrolling="no"></iframe>
该脚本应在您自己的服务器上运行。 您可以从网络运行任何 Brython 脚本。 使用 Brython,您只需在script
标签内键入 Python 代码。 看看这个 Brython 示例,或者只是浏览图库。
方法 B:将 Python 编译为 Javascript(无服务器,纯扩展)
有几种工具可以将 Python 编译为 Javascript。Rapydscript 可以正常工作,Pyjs 在 chrome 上无法正常使用(启动时需要特殊参数)。
使用以下命令安装 Rapydscript:
sudo apt-get install npm
sudo ln -s /usr/bin/nodejs /usr/bin/node
sudo npm install rapydscript
从此站点下载代码:
将文件/src/hello.py
更改为所需的文件:
# Example Python script
# (for rapydscript, a python to javascript compiler)
#def doHelloMessage():
# alert('hello')
#doHelloMessage()
# modify html page
document.getElementById("result").innerHTML = 'Compiled Python script in Chrome'
# write into log
console.log('hello from python')
运行:
./make.sh
您可以在/compiledpythonextension/
中找到您的扩展。 将其作为未打包的扩展程序加载到 chrome 中,并查看其工作情况 😃
结论:
Chrome 插件是使用 HTML,JavaScript 和 CSS 创建的。我们可以使用 Python 创建 Python 到 Javascript 编译器(Rapydscript)的常规 Chrome 扩展。
Python 的有趣技巧
启动简单的 HTTP Web 服务器
可以在几秒钟内启动简单的 HTTP 服务器。
python -m SimpleHTTPServer
对于 Python3:
python -m http.server
启动后,您可以打开 http://127.0.0.1:8000/。 浏览器将向您显示目录的内容。
有趣的文字
尝试以下语句来显示蒂姆·彼得斯的诗。
import this
XKCD 网络漫画
您可以使用以下方法在 XKCD 上打开漫画:
import antigravity
使用zip
合并数组
您可以使用以下命令压缩两个数组:
b = [[1, 2, 3, 4], [6, 5, 4, 3]]
zip(*b)
[(1, 6), (2, 5), (3, 4), (4, 3)]
反转列表
要反转列表,可以实现一个功能。 但是,如果已经实施,为什么还要麻烦解决呢?
b = [1,2,3,4,5]
b.reverse()
print b
[5, 4, 3, 2, 1]
反转字符串
可以使用以下方法来代替创建反向字符串的方法:
s = "Hello world"
s = s[::-1]
print s
dlrow olleH
交换变量
您无需定义临时变量即可交换为 Python 中的变量:
a = 1
b = 3
b,a = a,b
print a
print b
1
如果您知道任何提示或技巧,请发表评论。 😃
python 语音引擎教程
原文: https://pythonspot.com/speech-engines-with-python-tutorial/
文本到语音(TTS)
用于创建人工语音的计算机系统称为语音合成器,可以在软件或硬件产品中实现。
文本到语音(TTS)系统将普通语言文本转换为语音。 我们如何在 Python 中使用语音合成?
Pyttsx
Pyttsx 是一个跨平台(Mac OSX,Windows 和 Linux)的语音库。 您可以设置语音元数据,例如年龄,性别,ID,语言和姓名。 您的语音引擎带有大量语音。
文字转语音样本:
https://pythonspot.com/wp-content/uploads/2016/08/pytts.wav
安装方式:
sudo pip install pyttsx
创建代码Speech1.py
import pyttsx
engine = pyttsx.init()
engine.say('The quick brown fox jumped over the lazy dog.')
engine.runAndWait()
并使用 python 执行它。
eSpeak
eSpeak 是一款适用于 Linux 和 Windows 的紧凑型开源软件语音合成器,适用于英语和其他语言。
文字转语音样本:
https://pythonspot.com/wp-content/uploads/2016/08/espeak.wav
我们可以使用以下方法进行安装:
sudo apt-get install espeak
创建代码Speech2.py
:
import os
os.system("espeak 'The quick brown fox'")
它非常易于使用,但是像 pyttsx 一样听起来很机器人。
gTTS
我在 Github 上找到了一个使用 Google 语音引擎的脚本。 该脚本带有许多选项,并且不会说话,而是保存为 mp3。 我们添加了一个命令来自动播放 mp3:
os.system("mpg321 out.mp3 -quiet")
运行:
python gtts.py -s 'Python programming example'
声音非常自然。 唯一的缺点是,运行此脚本时需要与互联网连接。
链接
你可能会喜欢:
安卓系统
SL4A:Android Python 脚本
可以使用 Android 脚本层(SL4A)和适用于 Android 的 Python 解释器,在 Android 上运行 Python 脚本。
SL4A
SL4A 项目使在 Android 上编写脚本成为可能,它支持许多编程语言,包括 Python,Perl,Lua,BeanShell,JavaScript,JRuby 和 Shell。 SL4A 项目有很多 Google 的贡献者,但它不是 Google 的正式项目。
脚本可以访问 Android 特定的功能,例如呼叫,短信(SMS),拍照,文字转语音,蓝牙等等。
在本文中,您将学习如何使用 SL4A 在 Android 设备上运行 Python。
SL4A 专为开发人员设计
请记住,SL4A 是为开发人员和 alpha 质量软件设计的。
安装 SL4A
QR:SL4A APK 的链接
首先启用来自未知来源的程序的安装。默认情况下,Android 设备只能安装 Google Play 商店中的应用。
您必须通过转到“设置 -> 安全 -> 未知来源”并点击相应的框,以启用“从未知来源安装”权限。
更新这些设置后,请下载 SL4A APK。 在您的 Android 设备上访问 https://github.com/kuri65536/sl4a 并下载 SL4A APK( 或使用右侧的 QR 码)。
下载后,将弹出安装菜单,请求您的 Android 设备上的所有权限。
SL4A 权限
安装适用于 Android 的 Python 3
适用于 Android Python 3 的 QR Code
安装 Py4A 应用程序。Android 版 Python 应用程序仅在以下平台上运行
Android 设备。您应该将此应用程序与 SL4A 一起使用。
您可以选择任何版本的 Py4A,但请记住,Android 上支持的版本:
-
Python 2 需要 Android 设备> = 1.6
-
Python 3 需要 Android 设备> = 2.3.1
Git 仓库为:https://github.com/kuri65536/python-for-android/releases
您还可以通过 Android 设备上的 QR 扫描仪使用右侧的 QR 码。
一旦安装了 Py4A,启动应用程序,然后按安装。 这将安装 Python 解释器。
Android Python 3 安装
SL4A
再次打开 SL4A。 许多脚本将出现(在列表中)。 您现在可以在 Android 设备上运行 Python 脚本了!
Android 上的 Python
按下诸如talk.py
之类的程序,将会显示一个小弹出窗口。 按下终端图标将启动 Python 脚本。
SL4A Python 菜单
第三个按钮(铅笔)将打开一个编辑器。 这不是一个完善的 IDE,而是一个简单的编辑器。它没有语法突出显示。
在 Android 上编写脚本
您可能更喜欢自己喜欢的 Python 编辑器(这里是 vim/emacs 粉丝?PyCharm?Atom?)
所有脚本都存储在/sl4a/scripts/
中
注意:文件扩展名
如果您安装了 Python 3 解释器,则程序将以.py3
扩展名而不是.py
扩展名显示。
一个简单的程序(太空飞船发射):
"""TTS Rocket Launch."""
__author__ = 'Frank <[email protected]>'
import android
droid = android.Android()
message = "Python on Android"
droid.ttsSpeak(message)
for i in range(10,0,-1):
droid.ttsSpeak(str(i))
droid.ttsSpeak("We have lift off!")
droid.ttsSpeak("rrrrrr")
更多示例:
http://www.mattcutts.com/blog/android-barcode-scanner/
https://github.com/damonkohler/sl4a/blob/wiki/Tutorials.md
使用 QPython 在 Python 中进行 Android 开发
原文: https://pythonspot.com/android-development-in-python-with-qpython/
QPython 是一个脚本引擎,可让您在 Android 上运行 Python 脚本。 如果要制作 Android 应用,请改用 Kivy。
QPython
QPython 应用包含:
-
Android 上的 Python 编程
-
运行脚本/项目
-
Android 上的 IDE
-
点(包管理器)
-
SL4A 用于 Android 访问(GPS,网络,蓝牙等)
请注意,QPython 是脚本引擎,类似于 SL4A,而不是应用程序开发平台。
安装
在 Google Play 商店中,您可以找到 QPython(Python 2.7.2)和 QPython3(Python 3.2.2)。 我们建议您使用 Python 3.2.2,但出于传统原因,您可能希望使用 Python 2.7.2。
Android 上的 Python
用法
安装后,您将进入一个标志性菜单。 第一个图标将打开 Python 解释器。
qpython-menu
集成开发环境
第二个图标(编辑器)将启动 Python IDE。 它具有语法突出显示和其他一些功能。 虽然在 Android 设备上安装 IDE 很有用,但在手机或平板电脑上打字可能不是您的首选。所有脚本都存储在/storage/emulated/0/com.hipipal.qpyplus/scripts
中。您可以从桌面上喜欢的编辑器直接上传到此目录。(运行按钮在底部。)
QPython IDE
解释器
您可以直接在 Android 设备上使用 Python 解释器。这类似于在 Windows 或 Linux 上启动 Python 解释器。虽然有时有用,但您可能更喜欢使用 IDE。
Android 上的 Python 解释器
计算机视觉
图像数据和操作
OpenCV(cv2
)可用于从图像中提取数据并对其进行操作。 我们在下面演示一些示例:
图像属性
我们可以使用以下代码提取宽度,高度和颜色深度:
import cv2
import numpy as np
# read image into matrix.
m = cv2.imread("python.png")
# get image properties.
h,w,bpp = np.shape(m)
# print image properties.
print "width: " + str(w)
print "height: " + str(h)
print "bpp: " + str(bpp)
访问像素数据
我们可以直接使用矩阵访问图像的像素数据,例如:
import cv2
import numpy as np
# read image into matrix.
m = cv2.imread("python.png")
# get image properties.
h,w,bpp = np.shape(m)
# print pixel value
y = 1
x = 1
print m[y][x]
要遍历图像中的所有像素,可以使用:
import cv2
import numpy as np
# read image into matrix.
m = cv2.imread("python.png")
# get image properties.
h,w,bpp = np.shape(m)
# iterate over the entire image.
for py in range(0,h):
for px in range(0,w):
print m[py][px]
图像处理
您可以直接修改像素和像素通道(r, g, b
)。 在下面的示例中,我们删除了一个颜色通道:
import cv2
import numpy as np
# read image into matrix.
m = cv2.imread("python.png")
# get image properties.
h,w,bpp = np.shape(m)
# iterate over the entire image.
for py in range(0,h):
for px in range(0,w):
m[py][px][0] = 0
# display image
cv2.imshow('matrix', m)
cv2.waitKey(0)
要更改整个图像,您必须更改所有通道:m[py][px][0]
,m[py][px][1]
,m[py][px][2]
。
保存图像
您可以使用以下方法将修改后的图像保存到磁盘:
cv2.imwrite('filename.png',m)
图像直方图
直方图收集 n 个数据,这些数据被组织到一组箱子中。每个档位都显示频率。 OpenCV 可以为彩色和灰度图像生成直方图。 您可能需要将直方图用于计算机视觉任务。
直方图示例
给定图像,我们可以生成蓝色,绿色和红色值的直方图。
直方图计算
我们使用函数cv.CalcHist(image, channel, mask, histSize, range)
参数:
image
:应放在方括号中,类型为uint8
或float32
的源图像channel
:要选择的颜色通道。[0]
用于灰度。 彩色图像具有蓝色,绿色和红色通道mask
:如果您想要整个图像的直方图,则不适用,否则为一个区域。histSize
:箱数range
:颜色范围:
彩色图像的直方图:
# draw histogram in python.
import cv2
import numpy as np
img = cv2.imread('image.jpg')
h = np.zeros((300,256,3))
bins = np.arange(256).reshape(256,1)
color = [ (255,0,0),(0,255,0),(0,0,255) ]
for ch, col in enumerate(color):
hist_item = cv2.calcHist([img],[ch],None,[256],[0,255])
cv2.normalize(hist_item,hist_item,0,255,cv2.NORM_MINMAX)
hist=np.int32(np.around(hist_item))
pts = np.column_stack((bins,hist))
cv2.polylines(h,[pts],False,col)
h=np.flipud(h)
cv2.imshow('colorhist',h)
cv2.waitKey(0)
使用级联的汽车追踪
使用 OpenCV 进行汽车追踪
在本教程中,我们将研究使用 haar 特征的车辆跟踪。 我们有一个经过训练的 haar 级联文件。
该程序将检测感兴趣的区域,将其分类为汽车,并在其周围显示矩形。
级联检测
让我们从基本的级联检测程序开始:
#! /usr/bin/python
import cv2
face_cascade = cv2.CascadeClassifier('cars.xml')
vc = cv2.VideoCapture('road.avi')
if vc.isOpened():
rval , frame = vc.read()
else:
rval = False
while rval:
rval, frame = vc.read()
# car detection.
cars = face_cascade.detectMultiScale(frame, 1.1, 2)
ncars = 0
for (x,y,w,h) in cars:
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),2)
ncars = ncars + 1
# show result
cv2.imshow("Result",frame)
cv2.waitKey(1);
vc.release()
这样既可以检测屏幕中的汽车,也可以检测到噪声,并且屏幕有时会抖动。 为了避免所有这些情况,我们必须改进我们的汽车跟踪算法。 我们决定提出一个简单的解决方案。
汽车追踪算法
对于每一帧:
- 检测潜在的感兴趣区域
- 根据垂直,水平相似度过滤检测到的区域
- 如果是新区域,请添加到集合中
- 每 30 帧清除一次收藏
消除误报
均方误差函数用于消除误报。 我们比较图像的垂直和水平方向。 如果差异大或小,就不能成为汽车。
ROI 检测
可能无法在每帧中检测到汽车。 如果检测到新车,则将其添加到集合中。
我们将这个集合保留 30 帧,然后清除它。
#!/usr/bin/python
import cv2
import numpy as np
def diffUpDown(img):
# compare top and bottom size of the image
# 1\. cut image in two
# 2\. flip the top side
# 3\. resize to same size
# 4\. compare difference
height, width, depth = img.shape
half = height/2
top = img[0:half, 0:width]
bottom = img[half:half+half, 0:width]
top = cv2.flip(top,1)
bottom = cv2.resize(bottom, (32, 64))
top = cv2.resize(top, (32, 64))
return ( mse(top,bottom) )
def diffLeftRight(img):
# compare left and right size of the image
# 1\. cut image in two
# 2\. flip the right side
# 3\. resize to same size
# 4\. compare difference
height, width, depth = img.shape
half = width/2
left = img[0:height, 0:half]
right = img[0:height, half:half + half-1]
right = cv2.flip(right,1)
left = cv2.resize(left, (32, 64))
right = cv2.resize(right, (32, 64))
return ( mse(left,right) )
def mse(imageA, imageB):
err = np.sum((imageA.astype("float") - imageB.astype("float")) ** 2)
err /= float(imageA.shape[0] * imageA.shape[1])
return err
def isNewRoi(rx,ry,rw,rh,rectangles):
for r in rectangles:
if abs(r[0] - rx) < 40 and abs(r[1] - ry) < 40:
return False
return True
def detectRegionsOfInterest(frame, cascade):
scaleDown = 2
frameHeight, frameWidth, fdepth = frame.shape
# Resize
frame = cv2.resize(frame, (frameWidth/scaleDown, frameHeight/scaleDown))
frameHeight, frameWidth, fdepth = frame.shape
# haar detection.
cars = cascade.detectMultiScale(frame, 1.2, 1)
newRegions = []
minY = int(frameHeight*0.3)
# iterate regions of interest
for (x,y,w,h) in cars:
roi = [x,y,w,h]
roiImage = frame[y:y+h, x:x+w]
carWidth = roiImage.shape[0]
if y > minY:
diffX = diffLeftRight(roiImage)
diffY = round(diffUpDown(roiImage))
if diffX > 1600 and diffX < 3000 and diffY > 12000:
rx,ry,rw,rh = roi
newRegions.append( [rx*scaleDown,ry*scaleDown,rw*scaleDown,rh*scaleDown] )
return newRegions
def detectCars(filename):
rectangles = []
cascade = cv2.CascadeClassifier('cars.xml')
vc = cv2.VideoCapture(filename)
if vc.isOpened():
rval , frame = vc.read()
else:
rval = False
roi = [0,0,0,0]
frameCount = 0
while rval:
rval, frame = vc.read()
frameHeight, frameWidth, fdepth = frame.shape
newRegions = detectRegionsOfInterest(frame, cascade)
for region in newRegions:
if isNewRoi(region[0],region[1],region[2],region[3],rectangles):
rectangles.append(region)
for r in rectangles:
cv2.rectangle(frame,(r[0],r[1]),(r[0]+r[2],r[1]+r[3]),(0,0,255),3)
frameCount = frameCount + 1
if frameCount > 30:
frameCount = 0
rectangles = []
# show result
cv2.imshow("Result",frame)
cv2.waitKey(1);
vc.release()
detectCars('road.avi')
最后说明
级联不是旋转不变的,比例尺和平移的不变。 此外,检测具有 Haar 级联的车辆可能会相当不错,但是使用其他算法(显着点)也会有所收获。
您可能会喜欢:
Google Hangouts 视频中的人脸检测
在本教程中,您将学习如何在 Python 中应用人脸检测。 作为输入视频,我们将使用 Google Hangouts 视频。 网路上有大量的 Google Hangouts 视讯,在这些视讯中,人脸通常大到足以让软体侦测到人脸。
使用 OpenCV(Open Computer Vision)库实现面部检测。 最常见的面部检测方法是 haar 级联。已知该技术可以很好地与人脸检测配合使用。 您需要将级联文件(包含在 OpenCV 中)放在程序所在的目录中。
Python OpenCV 和视频
为了分析输入视频,我们提取每个帧。 每个帧显示的时间很短。 从这个基本程序开始:
#! /usr/bin/python
import cv2
vc = cv2.VideoCapture('video.mp4')
c=1
fps = 24
if vc.isOpened():
rval , frame = vc.read()
else:
rval = False
while rval:
rval, frame = vc.read()
cv2.imshow("Result",frame)
cv2.waitKey(1000 / fps);
vc.release()
执行后,您将看到没有声音播放的视频。(OpenCV 不支持声音)。在 while 循环内,我们将每个视频帧包含在可变帧内。
使用 OpenCV 进行人脸检测
我们将在脸部上方显示一个矩形。 为了避免矩形的闪烁,如果未检测到面部,我们将在最新的已知位置显示该矩形。
#! /usr/bin/python
import cv2
face_cascade = cv2.CascadeClassifier('lbpcascade_frontalface.xml')
vc = cv2.VideoCapture('video.mp4')
if vc.isOpened():
rval , frame = vc.read()
else:
rval = False
roi = [0,0,0,0]
while rval:
rval, frame = vc.read()
# resize frame for speed.
frame = cv2.resize(frame, (300,200))
# face detection.
faces = face_cascade.detectMultiScale(frame, 1.8, 2)
nfaces = 0
for (x,y,w,h) in faces:
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),2)
nfaces = nfaces + 1
roi = [x,y,w,h]
# undetected face, show old on position.
if nfaces == 0:
cv2.rectangle(frame,(roi[0],roi[1]),(roi[0]+roi[2],roi[1]+roi[3]),(0,0,255),2)
# show result
cv2.imshow("Result",frame)
cv2.waitKey(1);
vc.release()
在此程序中,我们仅假设视频屏幕中只有一张脸。 我们减小了屏幕尺寸,以加快处理时间。 在大多数情况下,这很好,因为检测将在较低的分辨率下正常工作。 如果要“实时”执行人脸检测,则必须缩短计算周期。 此实现的替代方法是先处理,然后再显示。
该技术的局限性在于它不能始终检测到面部,并且可能无法检测到很小或被遮挡的面部。 它可能显示出误报,例如被检测为人脸的袋子。 这种技术在某些类型的输入视频上效果很好。
使用模板进行对象检测
模板匹配是一种用于查找与补丁(模板)相似的图像区域的技术。
它的应用可以是机器人或制造业。
简介
补丁是具有某些功能的小图像。 模板匹配的目的是在图像中找到补丁/模板。
与 OpenCV 和 Python 匹配的模板。 模板(左),结果图像(右)
要找到它们,我们都需要:
-
源图像(
S
):在其中查找匹配项的空间 -
模板图像(
T
):模板图像
模板图像T
在源图像S
上滑动(在源图像上移动),并且程序尝试使用统计信息查找匹配项。
模板匹配示例
让我们看一下代码:
import numpy as np
import cv2
image = cv2.imread('photo.jpg')
template = cv2.imread('template.jpg')
# resize images
image = cv2.resize(image, (0,0), fx=0.5, fy=0.5)
template = cv2.resize(template, (0,0), fx=0.5, fy=0.5)
# Convert to grayscale
imageGray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
templateGray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
# Find template
result = cv2.matchTemplate(imageGray,templateGray, cv2.TM_CCOEFF)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
top_left = max_loc
h,w = templateGray.shape
bottom_right = (top_left[0] + w, top_left[1] + h)
cv2.rectangle(image,top_left, bottom_right,(0,0,255),4)
# Show result
cv2.imshow("Template", template)
cv2.imshow("Result", image)
cv2.moveWindow("Template", 10, 50);
cv2.moveWindow("Result", 150, 50);
cv2.waitKey(0)
说明
首先,我们使用imread()
加载源图像和模板图像。我们调整它们的大小并将其转换为灰度以便更快地进行检测:
image = cv2.imread('photo.jpg')
template = cv2.imread('template.jpg')
image = cv2.resize(image, (0,0), fx=0.5, fy=0.5)
template = cv2.resize(template, (0,0), fx=0.5, fy=0.5)
imageGray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
templateGray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
我们使用cv2.matchTemplate(image, template, method)
方法查找图像中最相似的区域。第三个参数是统计方法。
为您的应用选择正确的统计方法。TM_CCOEFF
(右),TM_SQDIFF
(左)
此方法具有六个匹配方法:CV_TM_SQDIFF
,CV_TM_SQDIFF_NORMED
,CV_TM_CCORR
,CV_TM_CCORR_NORMED
,CV_TM_CCOEFF
和CV_TM_CCOEFF_NORMED
。
这是完全不同的统计比较方法
最后,我们获得矩形变量并显示图像。
局限性
模板匹配不是比例不变的,也不是旋转不变的。 这是一种非常基本和直接的方法,可在其中找到最相关的区域。 因此,这种对象检测方法取决于您要构建的应用程序的类型。 对于非比例和旋转变化的输入,此方法效果很好。
Python 和 Netflix 点赞缩略图
原文: https://pythonspot.com/netflix-like-thumbnails-with-python/
受 Netflix 的启发,我们决定实施对焦点算法。 如果您在移动网站上使用生成的缩略图,则可能会增加 YouTube 视频的点击率(CTR)。
无论如何,这是一个有趣的实验。
焦点
所有图像都有一个感兴趣的区域,通常是人或脸。
找到关注区域的算法称为焦点算法。 给定输入图像,将基于关注区域创建一个新图像(缩略图)。
Python Netflix 点赞缩略图。来源:Google 视频。
从要用作缩略图的快照图像开始。 我们使用 Haar 功能查找图像中最有趣的区域。 Haar 级联文件可以在以下位置找到:
- https://raw.githubusercontent.com/Itseez/opencv/master/data/lbpcascades/lbpcascade_frontalface.xml
- https://github.com/adamhrv/HaarcascadeVisualizer
将这些文件下载到/data/
目录中。
#! /usr/bin/python
import cv2
bodyCascade = cv2.CascadeClassifier('data/haarcascade_mcs_upperbody.xml')
frame = cv2.imread('snapshot.png')
frameHeight, frameWidth, frameChannels = frame.shape
regions = bodyCascade.detectMultiScale(frame, 1.8, 2)
x,y,w,h = regions[0]
cv2.imwrite('thumbnail.png', frame[0:frameHeight,x:x+w])
cv2.rectangle(frame,(x,0),(x+w,frameHeight),(0,255,255),6)
cv2.imshow("Result",frame)
cv2.waitKey(0);
我们使用cv2.CascadeClassifier()
加载 haar 级联文件,并使用cv2.imread()
加载图像,然后bodyCascade.detectMultiScale()
使用已加载的 Haar 功能检测感兴趣的区域。
使用cv2.imwrite()
将图像另存为缩略图,最后显示图像并用矩形突出显示感兴趣的区域。 运行后,您将获得用于移动网页或应用程序的漂亮缩略图。
如果您还想同时检测身体和面部,可以使用:
#! /usr/bin/python
import cv2
bodyCascade = cv2.CascadeClassifier('data/haarcascade_mcs_upperbody.xml')
faceCascade = cv2.CascadeClassifier('data/lbpcascade_frontalface.xml')
frame = cv2.imread('snapshot2.png')
frameHeight, frameWidth, frameChannels = frame.shape
regions = bodyCascade.detectMultiScale(frame, 1.5, 2)
x,y,w,h = regions[0]
cv2.imwrite('thumbnail.png', frame[0:frameHeight,x:x+w])
cv2.rectangle(frame,(x,0),(x+w,frameHeight),(0,255,255),6)
faceregions = faceCascade.detectMultiScale(frame, 1.5, 2)
x,y,w,h = faceregions[0]
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),6)
cv2.imshow("Result",frame)
cv2.waitKey(0);
cv2.imwrite('out.png', frame)
游戏
Python 和简单文字游戏
在本文中,我们将演示如何创建一个简单的猜谜游戏。
游戏的目的是猜测正确的数字。
示例
下面运行示例:
使用 Python 的简单文字游戏
随机数
将要求用户猜测随机数。 我们首先选择随机数:
from random import randint
x = randint(1,9)
randint()
函数将选择一个介于 1 到 10 之间的伪随机数。然后,我们必须继续直到找到正确的数字为止:
guess = -1
print("Guess the number below 10:")
while guess != x:
guess = int(raw_input("Guess: "))
if guess != x:
print("Wrong guess")
else:
print("Guessed correctly")
Python 猜测游戏
下面的代码开始游戏:
from random import randint
x = randint(1,9)
guess = -1
print "Guess the number below 10:"
while guess != x:
guess = int(raw_input("Guess: "))
if guess != x:
print("Wrong guess")
else:
print("Guessed correctly")
运行示例:
Guess the number below 10:
Guess: 3
Wrong guess
Guess: 6
Wrong guess
..
用 Pygame 开发游戏
Pygame Python
欢迎来到该系列的第一篇教程:使用 Pygame 构建游戏。 使用 Pygame 创建的游戏可以在支持 Python 的任何计算机上运行,包括 Windows,Linux 和 Mac OS。
在本教程中,我们将解释使用 Pygame 构建游戏的基础。 我们将从基础开始,并教您如何创建基础框架。 在接下来的教程中,您将学习如何制作某些类型的游戏。
PyGame 简介
您将得到一个与右边的程序相似的程序:
游戏总是以与此类似的顺序(伪代码)开始:
initialize()
while running():
game_logic()
get_input()
update_screen()
deinitialize()
游戏从初始化开始。 已加载所有图形,已加载声音,已加载级别以及需要加载的任何数据。 游戏将继续运行,直到收到退出事件为止。 在此游戏循环中,我们更新游戏,获取输入并更新屏幕。 具体实现取决于游戏,但这种基本结构在所有游戏中都很常见。
在 Pygame 中,我们将其定义为:
import pygame
from pygame.locals import *
class App:
windowWidth = 640
windowHeight = 480
x = 10
y = 10
def __init__(self):
self._running = True
self._display_surf = None
self._image_surf = None
def on_init(self):
pygame.init()
self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
self._running = True
self._image_surf = pygame.image.load("pygame.png").convert()
def on_event(self, event):
if event.type == QUIT:
self._running = False
def on_loop(self):
pass
def on_render(self):
self._display_surf.blit(self._image_surf,(self.x,self.y))
pygame.display.flip()
def on_cleanup(self):
pygame.quit()
def on_execute(self):
if self.on_init() == False:
self._running = False
while( self._running ):
for event in pygame.event.get():
self.on_event(event)
self.on_loop()
self.on_render()
self.on_cleanup()
if __name__ == "__main__" :
theApp = App()
theApp.on_execute()
Pygame 程序以构造函数__init__()
开始。完成后,将调用on_execute()
。此方法运行游戏:更新事件,更新屏幕。最后,使用on_cleanup()
对游戏进行初始化。
在初始化阶段,我们设置屏幕分辨率并启动 Pygame 库:
def on_init(self):
pygame.init()
self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
我们还加载图像。
self._image_surf = pygame.image.load("pygame.png").convert()
这不会将图像绘制到屏幕上,而是发生在on_render()
中。
def on_render(self):
self._display_surf.blit(self._image_surf,(self.x,self.y))
pygame.display.flip()
blit
方法将图像(image_surf
)绘制到坐标(x, y)
。 在 Pygame 中,坐标从(0, 0)
左上角开始到(wind0wWidth, windowHeight)
。 方法调用pygame.display.flip()
更新屏幕。
继续下一个教程,并学习如何添加游戏逻辑和构建游戏 😃
Pygame 贪食蛇
在本教程中,您将学习如何制作蛇游戏。 该游戏是一款街机游戏,逻辑非常简单,这就是为什么它是演示如何使用 Pygame 构建游戏的理想示例的原因。
玩家被表示为蛇,如果它吃了一个苹果,蛇就会成长。 游戏的目的是在不撞到自己的情况下尽可能多地吃苹果。 在游戏的早期阶段这很容易,但是随着蛇的长度增加,难度变得越来越大。
入门:基本结构和事件处理。
我们定义了一个Player
类,它可以保持玩家在屏幕上的位置及其移动的速度。 另外,我们定义Player
实例可以执行的动作(动作):
class Player:
x = 10
y = 10
speed = 1
def moveRight(self):
self.x = self.x + self.speed
def moveLeft(self):
self.x = self.x - self.speed
def moveUp(self):
self.y = self.y - self.speed
def moveDown(self):
self.y = self.y + self.speed
可以使用移动方法创建玩家对象,并可以修改变量。
我们将这些方法链接到事件。 在 Pygame 中,我们可以使用以下代码获得非阻塞式键盘输入:
pygame.event.pump()
keys = pygame.key.get_pressed()
if (keys[K_RIGHT]):
print "Right arrow pressed."
完整的代码使我们能够在屏幕上移动玩家:
from pygame.locals import *
import pygame
class Player:
x = 10
y = 10
speed = 1
def moveRight(self):
self.x = self.x + self.speed
def moveLeft(self):
self.x = self.x - self.speed
def moveUp(self):
self.y = self.y - self.speed
def moveDown(self):
self.y = self.y + self.speed
class App:
windowWidth = 800
windowHeight = 600
player = 0
def __init__(self):
self._running = True
self._display_surf = None
self._image_surf = None
self.player = Player()
def on_init(self):
pygame.init()
self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
pygame.display.set_caption('Pygame pythonspot.com example')
self._running = True
self._image_surf = pygame.image.load("pygame.png").convert()
def on_event(self, event):
if event.type == QUIT:
self._running = False
def on_loop(self):
pass
def on_render(self):
self._display_surf.fill((0,0,0))
self._display_surf.blit(self._image_surf,(self.player.x,self.player.y))
pygame.display.flip()
def on_cleanup(self):
pygame.quit()
def on_execute(self):
if self.on_init() == False:
self._running = False
while( self._running ):
pygame.event.pump()
keys = pygame.key.get_pressed()
if (keys[K_RIGHT]):
self.player.moveRight()
if (keys[K_LEFT]):
self.player.moveLeft()
if (keys[K_UP]):
self.player.moveUp()
if (keys[K_DOWN]):
self.player.moveDown()
if (keys[K_ESCAPE]):
self._running = False
self.on_loop()
self.on_render()
self.on_cleanup()
if __name__ == "__main__" :
theApp = App()
theApp.on_execute()
现在,您可以使用箭头键在屏幕上移动该块。
pygame 的例子。在屏幕上移动块
构建玩家(蛇)
玩家控制具有初始长度的蛇。 按下箭头键时,这条蛇总是在移动并改变其移动方向。 为此,更新玩家类:
class Player:
x = 0
y = 0
speed = 32
direction = 0
def update(self):
if self.direction == 0:
self.x = self.x + self.speed
if self.direction == 1:
self.x = self.x - self.speed
if self.direction == 2:
self.y = self.y - self.speed
if self.direction == 3:
self.y = self.y + self.speed
def moveRight(self):
self.direction = 0
def moveLeft(self):
self.direction = 1
def moveUp(self):
self.direction = 2
def moveDown(self):
self.direction = 3
并且不要忘记增加游戏循环的延迟。
import time
...
time.sleep (100.0 / 1000.0);
它开始更多地起蛇的作用,但是还没有基本长度。 我们跟踪蛇的旧位置并移动蛇的头部。 我们还将绘制方法移到了蛇中。 复制代码,您将得到一条动静的蛇:
from pygame.locals import *
import pygame
import time
class Player:
x = []
y = []
step = 44
direction = 0
length = 3
updateCountMax = 2
updateCount = 0
def __init__(self, length):
self.length = length
for i in range(0,length):
self.x.append(0)
self.y.append(0)
def update(self):
self.updateCount = self.updateCount + 1
if self.updateCount > self.updateCountMax:
# update previous positions
for i in range(self.length-1,0,-1):
print "self.x[" + str(i) + "] = self.x[" + str(i-1) + "]"
self.x[i] = self.x[i-1]
self.y[i] = self.y[i-1]
# update position of head of snake
if self.direction == 0:
self.x[0] = self.x[0] + self.step
if self.direction == 1:
self.x[0] = self.x[0] - self.step
if self.direction == 2:
self.y[0] = self.y[0] - self.step
if self.direction == 3:
self.y[0] = self.y[0] + self.step
self.updateCount = 0
def moveRight(self):
self.direction = 0
def moveLeft(self):
self.direction = 1
def moveUp(self):
self.direction = 2
def moveDown(self):
self.direction = 3
def draw(self, surface, image):
for i in range(0,self.length):
surface.blit(image,(self.x[i],self.y[i]))
class App:
windowWidth = 800
windowHeight = 600
player = 0
def __init__(self):
self._running = True
self._display_surf = None
self._image_surf = None
self.player = Player(10)
def on_init(self):
pygame.init()
self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
pygame.display.set_caption('Pygame pythonspot.com example')
self._running = True
self._image_surf = pygame.image.load("pygame.png").convert()
def on_event(self, event):
if event.type == QUIT:
self._running = False
def on_loop(self):
self.player.update()
pass
def on_render(self):
self._display_surf.fill((0,0,0))
self.player.draw(self._display_surf, self._image_surf)
pygame.display.flip()
def on_cleanup(self):
pygame.quit()
def on_execute(self):
if self.on_init() == False:
self._running = False
while( self._running ):
pygame.event.pump()
keys = pygame.key.get_pressed()
if (keys[K_RIGHT]):
self.player.moveRight()
if (keys[K_LEFT]):
self.player.moveLeft()
if (keys[K_UP]):
self.player.moveUp()
if (keys[K_DOWN]):
self.player.moveDown()
if (keys[K_ESCAPE]):
self._running = False
self.on_loop()
self.on_render()
time.sleep (50.0 / 1000.0);
self.on_cleanup()
if __name__ == "__main__" :
theApp = App()
theApp.on_execute()
结果:
python 贪食蛇
游戏逻辑
蛇游戏有一些规则:
-
如果蛇吃了一个苹果,那么苹果会移动到新位置。
-
如果蛇吃了一个苹果,蛇的长度就会增加。
-
如果一条蛇自行倒下,请继续游戏。
我们首先创建一个新类,使我们能够创建苹果:
class Apple:
x = 0
y = 0
step = 44
def __init__(self,x,y):
self.x = x * self.step
self.y = y * self.step
def draw(self, surface, image):
surface.blit(image,(self.x, self.y))
为简单起见,我们将苹果显示为绿色立方体。 我们有这个基本代码,但是除了移动蛇和显示苹果外,它没有做太多的事情:
from pygame.locals import *
import pygame
import time
class Apple:
x = 0
y = 0
step = 44
def __init__(self,x,y):
self.x = x * self.step
self.y = y * self.step
def draw(self, surface, image):
surface.blit(image,(self.x, self.y))
class Player:
x = []
y = []
step = 44
direction = 0
length = 3
updateCountMax = 2
updateCount = 0
def __init__(self, length):
self.length = length
for i in range(0,length):
self.x.append(0)
self.y.append(0)
def update(self):
self.updateCount = self.updateCount + 1
if self.updateCount > self.updateCountMax:
# update previous positions
for i in range(self.length-1,0,-1):
print "self.x[" + str(i) + "] = self.x[" + str(i-1) + "]"
self.x[i] = self.x[i-1]
self.y[i] = self.y[i-1]
# update position of head of snake
if self.direction == 0:
self.x[0] = self.x[0] + self.step
if self.direction == 1:
self.x[0] = self.x[0] - self.step
if self.direction == 2:
self.y[0] = self.y[0] - self.step
if self.direction == 3:
self.y[0] = self.y[0] + self.step
self.updateCount = 0
def moveRight(self):
self.direction = 0
def moveLeft(self):
self.direction = 1
def moveUp(self):
self.direction = 2
def moveDown(self):
self.direction = 3
def draw(self, surface, image):
for i in range(0,self.length):
surface.blit(image,(self.x[i],self.y[i]))
class App:
windowWidth = 800
windowHeight = 600
player = 0
apple = 0
def __init__(self):
self._running = True
self._display_surf = None
self._image_surf = None
self._apple_surf = None
self.player = Player(10)
self.apple = Apple(5,5)
def on_init(self):
pygame.init()
self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
pygame.display.set_caption('Pygame pythonspot.com example')
self._running = True
self._image_surf = pygame.image.load("pygame.png").convert()
self._apple_surf = pygame.image.load("apple.png").convert()
def on_event(self, event):
if event.type == QUIT:
self._running = False
def on_loop(self):
self.player.update()
pass
def on_render(self):
self._display_surf.fill((0,0,0))
self.player.draw(self._display_surf, self._image_surf)
self.apple.draw(self._display_surf, self._apple_surf)
pygame.display.flip()
def on_cleanup(self):
pygame.quit()
def on_execute(self):
if self.on_init() == False:
self._running = False
while( self._running ):
pygame.event.pump()
keys = pygame.key.get_pressed()
if (keys[K_RIGHT]):
self.player.moveRight()
if (keys[K_LEFT]):
self.player.moveLeft()
if (keys[K_UP]):
self.player.moveUp()
if (keys[K_DOWN]):
self.player.moveDown()
if (keys[K_ESCAPE]):
self._running = False
self.on_loop()
self.on_render()
time.sleep (50.0 / 1000.0);
self.on_cleanup()
if __name__ == "__main__" :
theApp = App()
theApp.on_execute()
因此,我们必须添加游戏逻辑。 要知道蛇的位置是否与苹果的位置匹配,我们必须进行碰撞检测。 这只是意味着要使蛇的坐标与苹果的坐标相交。 我们创建一个新方法来做到这一点:
def isCollision(self,x1,y1,x2,y2,bsize):
if x1 >= x2 and x1 <= x2 + bsize:
if y1 >= y2 and y1 <= y2 + bsize:
return True
return False
给定其块大小bsize
,如果坐标(x1, y1)
与(x2, y2)
相交,则它将返回True
。 我们调用此方法来确定蛇是否与苹果碰撞。 我们需要检查整个蛇,而不仅是头部,因为我们不希望苹果的新位置位于蛇的某个位置。 我们使用相同的isCollision
方法来确定蛇是否与自身碰撞(等于输掉游戏)。
完整来源:
from pygame.locals import *
from random import randint
import pygame
import time
class Apple:
x = 0
y = 0
step = 44
def __init__(self,x,y):
self.x = x * self.step
self.y = y * self.step
def draw(self, surface, image):
surface.blit(image,(self.x, self.y))
class Player:
x = [0]
y = [0]
step = 44
direction = 0
length = 3
updateCountMax = 2
updateCount = 0
def __init__(self, length):
self.length = length
for i in range(0,2000):
self.x.append(-100)
self.y.append(-100)
# initial positions, no collision.
self.x[1] = 1*44
self.x[2] = 2*44
def update(self):
self.updateCount = self.updateCount + 1
if self.updateCount > self.updateCountMax:
# update previous positions
for i in range(self.length-1,0,-1):
self.x[i] = self.x[i-1]
self.y[i] = self.y[i-1]
# update position of head of snake
if self.direction == 0:
self.x[0] = self.x[0] + self.step
if self.direction == 1:
self.x[0] = self.x[0] - self.step
if self.direction == 2:
self.y[0] = self.y[0] - self.step
if self.direction == 3:
self.y[0] = self.y[0] + self.step
self.updateCount = 0
def moveRight(self):
self.direction = 0
def moveLeft(self):
self.direction = 1
def moveUp(self):
self.direction = 2
def moveDown(self):
self.direction = 3
def draw(self, surface, image):
for i in range(0,self.length):
surface.blit(image,(self.x[i],self.y[i]))
class Game:
def isCollision(self,x1,y1,x2,y2,bsize):
if x1 >= x2 and x1 <= x2 + bsize:
if y1 >= y2 and y1 <= y2 + bsize:
return True
return False
class App:
windowWidth = 800
windowHeight = 600
player = 0
apple = 0
def __init__(self):
self._running = True
self._display_surf = None
self._image_surf = None
self._apple_surf = None
self.game = Game()
self.player = Player(3)
self.apple = Apple(5,5)
def on_init(self):
pygame.init()
self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
pygame.display.set_caption('Pygame pythonspot.com example')
self._running = True
self._image_surf = pygame.image.load("block.jpg").convert()
self._apple_surf = pygame.image.load("block.jpg").convert()
def on_event(self, event):
if event.type == QUIT:
self._running = False
def on_loop(self):
self.player.update()
# does snake eat apple?
for i in range(0,self.player.length):
if self.game.isCollision(self.apple.x,self.apple.y,self.player.x[i], self.player.y[i],44):
self.apple.x = randint(2,9) * 44
self.apple.y = randint(2,9) * 44
self.player.length = self.player.length + 1
# does snake collide with itself?
for i in range(2,self.player.length):
if self.game.isCollision(self.player.x[0],self.player.y[0],self.player.x[i], self.player.y[i],40):
print("You lose! Collision: ")
print("x[0] (" + str(self.player.x[0]) + "," + str(self.player.y[0]) + ")")
print("x[" + str(i) + "] (" + str(self.player.x[i]) + "," + str(self.player.y[i]) + ")")
exit(0)
pass
def on_render(self):
self._display_surf.fill((0,0,0))
self.player.draw(self._display_surf, self._image_surf)
self.apple.draw(self._display_surf, self._apple_surf)
pygame.display.flip()
def on_cleanup(self):
pygame.quit()
def on_execute(self):
if self.on_init() == False:
self._running = False
while( self._running ):
pygame.event.pump()
keys = pygame.key.get_pressed()
if (keys[K_RIGHT]):
self.player.moveRight()
if (keys[K_LEFT]):
self.player.moveLeft()
if (keys[K_UP]):
self.player.moveUp()
if (keys[K_DOWN]):
self.player.moveDown()
if (keys[K_ESCAPE]):
self._running = False
self.on_loop()
self.on_render()
time.sleep (50.0 / 1000.0);
self.on_cleanup()
if __name__ == "__main__" :
theApp = App()
theApp.on_execute()
结论:
您学习了如何使用 Python 创建游戏蛇以及碰撞检测,图像加载和事件处理等概念。 可以向这个小玩具游戏添加很多东西,但这只是一个非常简单的示例。😃
Pygame 中的迷宫
在本教程中,您将学习如何构建迷宫游戏。 这个想法只是用箭头键在迷宫中移动。
入门:基本结构和事件处理。
我们定义了一个Player
类,它可以保持玩家在屏幕上的位置及其移动的速度。 另外,我们定义Player
实例可以执行的动作(动作):
class Player:
x = 10
y = 10
speed = 1
def moveRight(self):
self.x = self.x + self.speed
def moveLeft(self):
self.x = self.x - self.speed
def moveUp(self):
self.y = self.y - self.speed
def moveDown(self):
self.y = self.y + self.speed
可以使用移动方法创建玩家对象,并可以修改变量。 我们将这些方法链接到事件。 在 Pygame 中,我们可以使用以下代码获得非阻塞式键盘输入:
pygame.event.pump()
keys = pygame.key.get_pressed()
if (keys[K_RIGHT]):
print "Right arrow pressed."
完整的代码使我们能够在屏幕上移动播放器:
from pygame.locals import *
import pygame
class Player:
x = 10
y = 10
speed = 1
def moveRight(self):
self.x = self.x + self.speed
def moveLeft(self):
self.x = self.x - self.speed
def moveUp(self):
self.y = self.y - self.speed
def moveDown(self):
self.y = self.y + self.speed
class App:
windowWidth = 800
windowHeight = 600
player = 0
def __init__(self):
self._running = True
self._display_surf = None
self._image_surf = None
self.player = Player()
def on_init(self):
pygame.init()
self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
pygame.display.set_caption('Pygame pythonspot.com example')
self._running = True
self._image_surf = pygame.image.load("pygame.png").convert()
def on_event(self, event):
if event.type == QUIT:
self._running = False
def on_loop(self):
pass
def on_render(self):
self._display_surf.fill((0,0,0))
self._display_surf.blit(self._image_surf,(self.player.x,self.player.y))
pygame.display.flip()
def on_cleanup(self):
pygame.quit()
def on_execute(self):
if self.on_init() == False:
self._running = False
while( self._running ):
pygame.event.pump()
keys = pygame.key.get_pressed()
if (keys[K_RIGHT]):
self.player.moveRight()
if (keys[K_LEFT]):
self.player.moveLeft()
if (keys[K_UP]):
self.player.moveUp()
if (keys[K_DOWN]):
self.player.moveDown()
if (keys[K_ESCAPE]):
self._running = False
self.on_loop()
self.on_render()
self.on_cleanup()
if __name__ == "__main__" :
theApp = App()
theApp.on_execute()
现在,您可以使用箭头键在屏幕上移动该块。
pygame
创建迷宫
我们定义一个 NxM 矩阵来表示迷宫块的位置。 在此矩阵中,元素 1 表示存在一个块,元素 0 表示不存在。
class Maze:
def __init__(self):
self.M = 10
self.N = 8
self.maze = [ 1,1,1,1,1,1,1,1,1,1,
1,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,1,
1,0,1,1,1,1,1,1,0,1,
1,0,1,0,0,0,0,0,0,1,
1,0,1,0,1,1,1,1,0,1,
1,0,0,0,0,0,0,0,0,1,
1,1,1,1,1,1,1,1,1,1,]
我们有完整的代码来绘制迷宫:
from pygame.locals import *
import pygame
class Player:
x = 44
y = 44
speed = 1
def moveRight(self):
self.x = self.x + self.speed
def moveLeft(self):
self.x = self.x - self.speed
def moveUp(self):
self.y = self.y - self.speed
def moveDown(self):
self.y = self.y + self.speed
class Maze:
def __init__(self):
self.M = 10
self.N = 8
self.maze = [ 1,1,1,1,1,1,1,1,1,1,
1,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,1,
1,0,1,1,1,1,1,1,0,1,
1,0,1,0,0,0,0,0,0,1,
1,0,1,0,1,1,1,1,0,1,
1,0,0,0,0,0,0,0,0,1,
1,1,1,1,1,1,1,1,1,1,]
def draw(self,display_surf,image_surf):
bx = 0
by = 0
for i in range(0,self.M*self.N):
if self.maze[ bx + (by*self.M) ] == 1:
display_surf.blit(image_surf,( bx * 44 , by * 44))
bx = bx + 1
if bx > self.M-1:
bx = 0
by = by + 1
class App:
windowWidth = 800
windowHeight = 600
player = 0
def __init__(self):
self._running = True
self._display_surf = None
self._image_surf = None
self._block_surf = None
self.player = Player()
self.maze = Maze()
def on_init(self):
pygame.init()
self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
pygame.display.set_caption('Pygame pythonspot.com example')
self._running = True
self._image_surf = pygame.image.load("player.png").convert()
self._block_surf = pygame.image.load("block.png").convert()
def on_event(self, event):
if event.type == QUIT:
self._running = False
def on_loop(self):
pass
def on_render(self):
self._display_surf.fill((0,0,0))
self._display_surf.blit(self._image_surf,(self.player.x,self.player.y))
self.maze.draw(self._display_surf, self._block_surf)
pygame.display.flip()
def on_cleanup(self):
pygame.quit()
def on_execute(self):
if self.on_init() == False:
self._running = False
while( self._running ):
pygame.event.pump()
keys = pygame.key.get_pressed()
if (keys[K_RIGHT]):
self.player.moveRight()
if (keys[K_LEFT]):
self.player.moveLeft()
if (keys[K_UP]):
self.player.moveUp()
if (keys[K_DOWN]):
self.player.moveDown()
if (keys[K_ESCAPE]):
self._running = False
self.on_loop()
self.on_render()
self.on_cleanup()
if __name__ == "__main__" :
theApp = App()
theApp.on_execute()
迷宫
结论
您学习了如何在 Python 中创建 2d 迷宫。 现在,您可能想要添加在上一教程中显示的碰撞检测。 因为我们已经解释了这个概念,所以我们不再赘述 😃
Pygame 中的贪食蛇 AI
在本文中,我们将向您展示如何创建基本的游戏 AI(人工智能)。 本文将介绍游戏蛇的 AI。
在此游戏(蛇)中,计算机和您都在玩蛇,而计算机蛇会尝试抓住您。 简而言之:对手 AI 会根据您在棋盘上的位置尝试确定并前往目的地。
添加计算机玩家:
我们使用名为Computer
的新类扩展了代码,它将成为我们的计算机玩家。 这包含绘制和移动计算机蛇的例程。
class Computer:
x = [0]
y = [0]
step = 44
direction = 0
length = 3
updateCountMax = 2
updateCount = 0
def __init__(self, length):
self.length = length
for i in range(0,2000):
self.x.append(-100)
self.y.append(-100)
# initial positions, no collision.
self.x[0] = 1*44
self.y[0] = 4*44
def update(self):
self.updateCount = self.updateCount + 1
if self.updateCount > self.updateCountMax:
# update previous positions
for i in range(self.length-1,0,-1):
self.x[i] = self.x[i-1]
self.y[i] = self.y[i-1]
# update position of head of snake
if self.direction == 0:
self.x[0] = self.x[0] + self.step
if self.direction == 1:
self.x[0] = self.x[0] - self.step
if self.direction == 2:
self.y[0] = self.y[0] - self.step
if self.direction == 3:
self.y[0] = self.y[0] + self.step
self.updateCount = 0
def moveRight(self):
self.direction = 0
def moveLeft(self):
self.direction = 1
def moveUp(self):
self.direction = 2
def moveDown(self):
self.direction = 3
def draw(self, surface, image):
for i in range(0,self.length):
surface.blit(image,(self.x[i],self.y[i]))
然后,我们调用计算机的更新和绘制方法。
def on_loop(self):
self.player.update()
self.computer.update()
....
def on_render(self):
self._display_surf.fill((0,0,0))
self.player.draw(self._display_surf, self._image_surf)
self.apple.draw(self._display_surf, self._apple_surf)
self.computer.draw(self._display_surf, self._image_surf)
pygame.display.flip()
这将使计算机蛇移动并在屏幕上绘制。 它具有与人类玩家相同的属性。
为计算机玩家添加智能
因为这是一个简单的游戏,所以我们无需在游戏内部创建完整的思维机。 我们只需要计算机玩家展示一些基本情报即可。 游戏中的智能通常非常有限,因为在大多数情况下,不需要复杂性或根本没有时间实现聪明的算法。
我们将添加的算法将仅到达目的地。 它将忽略任何障碍(人类玩家)。
def target(self,dx,dy):
if self.x[0] > dx:
self.moveLeft()
if self.x[0] < dx:
self.moveRight()
if self.x[0] == dx:
if self.y[0] < dy:
self.moveDown()
if self.y[0] > dy:
self.moveUp()
完整代码
我们得到以下完整代码:
from pygame.locals import *
from random import randint
import pygame
import time
class Apple:
x = 0
y = 0
step = 44
def __init__(self,x,y):
self.x = x * self.step
self.y = y * self.step
def draw(self, surface, image):
surface.blit(image,(self.x, self.y))
class Player:
x = [0]
y = [0]
step = 44
direction = 0
length = 3
updateCountMax = 2
updateCount = 0
def __init__(self, length):
self.length = length
for i in range(0,2000):
self.x.append(-100)
self.y.append(-100)
# initial positions, no collision.
self.x[0] = 1*44
self.x[0] = 2*44
def update(self):
self.updateCount = self.updateCount + 1
if self.updateCount > self.updateCountMax:
# update previous positions
for i in range(self.length-1,0,-1):
self.x[i] = self.x[i-1]
self.y[i] = self.y[i-1]
# update position of head of snake
if self.direction == 0:
self.x[0] = self.x[0] + self.step
if self.direction == 1:
self.x[0] = self.x[0] - self.step
if self.direction == 2:
self.y[0] = self.y[0] - self.step
if self.direction == 3:
self.y[0] = self.y[0] + self.step
self.updateCount = 0
def moveRight(self):
self.direction = 0
def moveLeft(self):
self.direction = 1
def moveUp(self):
self.direction = 2
def moveDown(self):
self.direction = 3
def draw(self, surface, image):
for i in range(0,self.length):
surface.blit(image,(self.x[i],self.y[i]))
class Computer:
x = [0]
y = [0]
step = 44
direction = 0
length = 3
updateCountMax = 2
updateCount = 0
def __init__(self, length):
self.length = length
for i in range(0,2000):
self.x.append(-100)
self.y.append(-100)
# initial positions, no collision.
self.x[0] = 1*44
self.y[0] = 4*44
def update(self):
self.updateCount = self.updateCount + 1
if self.updateCount > self.updateCountMax:
# update previous positions
for i in range(self.length-1,0,-1):
self.x[i] = self.x[i-1]
self.y[i] = self.y[i-1]
# update position of head of snake
if self.direction == 0:
self.x[0] = self.x[0] + self.step
if self.direction == 1:
self.x[0] = self.x[0] - self.step
if self.direction == 2:
self.y[0] = self.y[0] - self.step
if self.direction == 3:
self.y[0] = self.y[0] + self.step
self.updateCount = 0
def moveRight(self):
self.direction = 0
def moveLeft(self):
self.direction = 1
def moveUp(self):
self.direction = 2
def moveDown(self):
self.direction = 3
def target(self,dx,dy):
if self.x[0] > dx:
self.moveLeft()
if self.x[0] < dx:
self.moveRight()
if self.x[0] == dx:
if self.y[0] < dy:
self.moveDown()
if self.y[0] > dy:
self.moveUp()
def draw(self, surface, image):
for i in range(0,self.length):
surface.blit(image,(self.x[i],self.y[i]))
class Game:
def isCollision(self,x1,y1,x2,y2,bsize):
if x1 >= x2 and x1 <= x2 + bsize:
if y1 >= y2 and y1 <= y2 + bsize:
return True
return False
class App:
windowWidth = 800
windowHeight = 600
player = 0
apple = 0
def __init__(self):
self._running = True
self._display_surf = None
self._image_surf = None
self._apple_surf = None
self.game = Game()
self.player = Player(5)
self.apple = Apple(8,5)
self.computer = Computer(5)
def on_init(self):
pygame.init()
self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
pygame.display.set_caption('Pygame pythonspot.com example')
self._running = True
self._image_surf = pygame.image.load("pygame.png").convert()
self._apple_surf = pygame.image.load("apple.png").convert()
def on_event(self, event):
if event.type == QUIT:
self._running = False
def on_loop(self):
self.computer.target(self.apple.x, self.apple.y)
self.player.update()
self.computer.update()
# does snake eat apple?
for i in range(0,self.player.length):
if self.game.isCollision(self.apple.x,self.apple.y,self.player.x[i], self.player.y[i],44):
self.apple.x = randint(2,9) * 44
self.apple.y = randint(2,9) * 44
self.player.length = self.player.length + 1
# does computer eat apple?
for i in range(0,self.player.length):
if self.game.isCollision(self.apple.x,self.apple.y,self.computer.x[i], self.computer.y[i],44):
self.apple.x = randint(2,9) * 44
self.apple.y = randint(2,9) * 44
#self.computer.length = self.computer.length + 1
# does snake collide with itself?
for i in range(2,self.player.length):
if self.game.isCollision(self.player.x[0],self.player.y[0],self.player.x[i], self.player.y[i],40):
print "You lose! Collision: "
print "x[0] (" + str(self.player.x[0]) + "," + str(self.player.y[0]) + ")"
print "x[" + str(i) + "] (" + str(self.player.x[i]) + "," + str(self.player.y[i]) + ")"
exit(0)
pass
def on_render(self):
self._display_surf.fill((0,0,0))
self.player.draw(self._display_surf, self._image_surf)
self.apple.draw(self._display_surf, self._apple_surf)
self.computer.draw(self._display_surf, self._image_surf)
pygame.display.flip()
def on_cleanup(self):
pygame.quit()
def on_execute(self):
if self.on_init() == False:
self._running = False
while( self._running ):
pygame.event.pump()
keys = pygame.key.get_pressed()
if (keys[K_RIGHT]):
self.player.moveRight()
if (keys[K_LEFT]):
self.player.moveLeft()
if (keys[K_UP]):
self.player.moveUp()
if (keys[K_DOWN]):
self.player.moveDown()
if (keys[K_ESCAPE]):
self._running = False
self.on_loop()
self.on_render()
time.sleep (50.0 / 1000.0);
self.on_cleanup()
if __name__ == "__main__" :
theApp = App()
theApp.on_execute()
python 贪食蛇
结论
您学习了如何使用非常简单的 AI 算法创建基本的计算机玩家。
Pygame 中的跳和跑
在本文中,您将学习如何在 Pygame 中实现跳和跑逻辑。 为此,我们将实现玩家逻辑。
移动
左右移动与上一教程类似,只是意味着更改玩家的(x, y)
位置。 对于跳跃,我们使用经典力学中的公式:
F = 1/2 * m * v^2
其中F
是向上/向下的力,m
是物体的质量,v
是速度。 速度会随着时间的推移而下降,因为在此模拟中,当玩家跳跃时速度不会增加更多。 如果玩家到达地面,则跳跃结束。 在 Python 中,我们设置了一个变量isjump
来指示玩家是否在跳跃。 如果是玩家,则其位置将根据以上公式进行更新。
完整代码:
from pygame.locals import *
import pygame
import math
from time import sleep
class Player:
x = 10
y = 500
speed = 10
# Stores if player is jumping or not.
isjump = 0
# Force (v) up and mass m.
v = 8
m = 2
def moveRight(self):
self.x = self.x + self.speed
def moveLeft(self):
self.x = self.x - self.speed
def jump(self):
self.isjump = 1
def update(self):
if self.isjump:
# Calculate force (F). F = 0.5 * mass * velocity^2.
if self.v > 0:
F = ( 0.5 * self.m * (self.v*self.v) )
else:
F = -( 0.5 * self.m * (self.v*self.v) )
# Change position
self.y = self.y - F
# Change velocity
self.v = self.v - 1
# If ground is reached, reset variables.
if self.y >= 500:
self.y = 500
self.isjump = 0
self.v = 8
class App:
windowWidth = 800
windowHeight = 600
player = 0
def __init__(self):
self._running = True
self._display_surf = None
self._image_surf = None
self.player = Player()
def on_init(self):
pygame.init()
self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
pygame.display.set_caption('Pygame pythonspot.com example')
self._running = True
self._image_surf = pygame.image.load("pygame.png").convert()
def on_event(self, event):
if event.type == QUIT:
self._running = False
def on_loop(self):
pass
def on_render(self):
self._display_surf.fill((0,0,0))
self._display_surf.blit(self._image_surf,(self.player.x,self.player.y))
self.player.update()
pygame.display.flip()
sleep(0.03)
def on_cleanup(self):
pygame.quit()
def on_execute(self):
if self.on_init() == False:
self._running = False
while( self._running ):
pygame.event.pump()
keys = pygame.key.get_pressed()
if (keys[K_RIGHT]):
self.player.moveRight()
if (keys[K_LEFT]):
self.player.moveLeft()
if (keys[K_UP]):
self.player.jump()
if (keys[K_ESCAPE]):
self._running = False
self.on_loop()
self.on_render()
self.on_cleanup()
if __name__ == "__main__" :
theApp = App()
theApp.on_execute()
如果要跳跃对象,只需将它们添加到屏幕上,进行碰撞检测,如果碰撞为true
,则重置跳跃变量。
机器人技术
使用 Google Speech API 进行语音识别
原文: https://pythonspot.com/speech-recognition-using-google-speech-api/
Google 具有出色的语音识别 API。 该 API 将语音文本(麦克风)转换为书面文本(Python 字符串),即语音到文本。 您只需在麦克风中讲话即可,Google API 会将其翻译成书面文字。 该 API 对于英语具有出色的效果。
Google 还创建了 JavaScript Web Speech API,因此您可以根据需要在 JavaScript 中识别语音,以下是此链接:https://www.google.com/intl/zh-CN/chrome/demos/speech.html。 要在网络上使用它,您将需要 Google Chrome 25 版或更高版本。
安装
Google Speech API v2 每天最多只能查询 50 个查询。确保您的麦克风良好。
您是否正在寻找文字转语音?
这是 Ubuntu Linux 的安装指南。 但这可能在其他平台上也很好。 您将需要安装一些软件包:PyAudio,PortAudio 和 SpeechRecognition。 PyAudio 0.2.9 是必需的,您可能需要手动进行编译。
git clone http://people.csail.mit.edu/hubert/git/pyaudio.git
cd pyaudio
sudo python setup.py install
sudo apt-get installl libportaudio-dev
sudo apt-get install python-dev
sudo apt-get install libportaudio0 libportaudio2 libportaudiocpp0 portaudio19-dev
sudo pip3 install SpeechRecognition
程序
该程序将记录来自麦克风的音频,将其发送到语音 API 并返回 Python 字符串。
使用语音识别模块记录音频,该模块将包括在程序顶部。 其次,我们将录制的语音发送到 Google 语音识别 API,然后该 API 返回输出。
r.recognize_google(audio)
返回一个字符串。
#!/usr/bin/env python3
# Requires PyAudio and PySpeech.
import speech_recognition as sr
# Record Audio
r = sr.Recognizer()
with sr.Microphone() as source:
print("Say something!")
audio = r.listen(source)
# Speech recognition using Google Speech Recognition
try:
# for testing purposes, we're just using the default API key
# to use another API key, use `r.recognize_google(audio, key="GOOGLE_SPEECH_RECOGNITION_API_KEY")`
# instead of `r.recognize_google(audio)`
print("You said: " + r.recognize_google(audio))
except sr.UnknownValueError:
print("Google Speech Recognition could not understand audio")
except sr.RequestError as e:
print("Could not request results from Google Speech Recognition service; {0}".format(e))
您可能会喜欢:个人助理 Jarvis(语音识别和文本到语音)或语音引擎
Python 中的个人助理(Jarvis)
原文: https://pythonspot.com/personal-assistant-jarvis-in-python/
我认为在 Python 中创建个人助理很酷。 如果您喜欢电影,可能已经听说过 A.I. Jarvis。 钢铁侠电影中的角色 在本教程中,我们将创建 机器人。
我要拥有的功能是:
- 识别语音(语音识别)
- 口头回答(文本到语音)
- 回答简单的命令
对于本教程,您将需要(Ubuntu)Linux,Python 和可正常使用的麦克风。
视频
这是您要创建的(观看整个视频,最后是演示):
https://www.youtube-nocookie.com/embed/ErGAhUa_rlA?rel=0
识别语音
可以使用 Python 语音识别模块完成语音识别。我们使用 Google Speech API,因为它的质量很高。
以语音回答(文字转语音)
各种 API 和程序可用于文本到语音的应用程序。Espeak 和 pyttsx 开箱即用,但听起来很机器人。我们决定使用 Google 文字到语音 API gTTS。
sudo pip install gTTS
使用它很简单:
from gtts import gTTS
import os
tts = gTTS(text='Hello World', lang='en')
tts.save("hello.mp3")
os.system("mpg321 hello.mp3")
完整程序
下面的程序将回答口头问题。
#!/usr/bin/env python3
# Requires PyAudio and PySpeech.
import speech_recognition as sr
from time import ctime
import time
import os
from gtts import gTTS
def speak(audioString):
print(audioString)
tts = gTTS(text=audioString, lang='en')
tts.save("audio.mp3")
os.system("mpg321 audio.mp3")
def recordAudio():
# Record Audio
r = sr.Recognizer()
with sr.Microphone() as source:
print("Say something!")
audio = r.listen(source)
# Speech recognition using Google Speech Recognition
data = ""
try:
# Uses the default API key
# To use another API key: `r.recognize_google(audio, key="GOOGLE_SPEECH_RECOGNITION_API_KEY")`
data = r.recognize_google(audio)
print("You said: " + data)
except sr.UnknownValueError:
print("Google Speech Recognition could not understand audio")
except sr.RequestError as e:
print("Could not request results from Google Speech Recognition service; {0}".format(e))
return data
def jarvis(data):
if "how are you" in data:
speak("I am fine")
if "what time is it" in data:
speak(ctime())
if "where is" in data:
data = data.split(" ")
location = data[2]
speak("Hold on Frank, I will show you where " + location + " is.")
os.system("chromium-browser https://www.google.nl/maps/place/" + location + "/&")
# initialization
time.sleep(2)
speak("Hi Frank, what can I do for you?")
while 1:
data = recordAudio()
jarvis(data)
相关文章:
PyQt5 窗口
如果您尚未安装 PyQT5 ,则应先安装。 在终端中,您可以输入:
sudo apt-get install python3-pyqt5
如果您使用 Windows 或 Mac 计算机,则可以从以下网站下载 PyQT5:https://www.riverbankcomputing.com/software/pyqt/download5
PyQt5 窗口
您可以使用以下代码创建 PyQT5 窗口:
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QIcon
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'PyQt5 simple window - pythonspot.com'
self.left = 10
self.top = 10
self.width = 640
self.height = 480
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
我们使用setGeometry(left, top, width, height)
方法设置窗口大小。 使用setWindowTitle(title)
设置窗口标题。 最后调用show()
以显示窗口。
运行:
python3 window.py
输出看起来应该类似于上面的屏幕截图(取决于您的操作系统)。
PyQt5 按钮
PyQt5 支持使用QPushButton
类的按钮。 此类在PyQt5.QtWidgets
组中。 可以通过调用构造函数QPushButton
并将其文本显示为参数来创建按钮。
简介
要将按钮用于 PyQt5 应用程序,我们需要更新导入行:
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
from PyQt5.QtCore import pyqtSlot
在initUI()
方法中,添加以下代码行:
button = QPushButton('PyQt5 button', self)
button.setToolTip('This is an example button')
button.move(100,70)
QPushButton
创建小部件,第一个参数是按钮上的文本。 当用户将鼠标指向按钮时,setToolTip
方法显示消息。 最后,将按钮移动到坐标x = 100
,y = 70
。 我们需要为按钮单击创建一种方法:
@pyqtSlot()
def on_click(self):
print('PyQt5 button click')
使用以下命令将连接方法添加到单击:
button.clicked.connect(self.on_click)
最终 PyQt5 按钮代码:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'PyQt5 button - pythonspot.com'
self.left = 10
self.top = 10
self.width = 320
self.height = 200
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
button = QPushButton('PyQt5 button', self)
button.setToolTip('This is an example button')
button.move(100,70)
button.clicked.connect(self.on_click)
self.show()
@pyqtSlot()
def on_click(self):
print('PyQt5 button click')
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
上面的 PyQt5 按钮示例的屏幕截图。
PyQt5 消息框
在本文中,您将学习如何创建 PyQt5 消息框:
为了显示一个消息框,我们需要导入QMessageBox
。
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QMessageBox
我们使用方法QMessageBox.question()
显示消息框。
PyQt5 消息框代码
复制以下代码以显示消息框。
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QMessageBox
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'PyQt5 messagebox - pythonspot.com'
self.left = 10
self.top = 10
self.width = 320
self.height = 200
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
buttonReply = QMessageBox.question(self, 'PyQt5 message', "Do you like PyQt5?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if buttonReply == QMessageBox.Yes:
print('Yes clicked.')
else:
print('No clicked.')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
消息框的更多按钮
考虑到我们使用QMessageBox.Yes
和QMessageBox.No
。 我们可以轻松添加其他选项:
buttonReply = QMessageBox.question(self, 'PyQt5 message', "Do you want to save?", QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel, QMessageBox.Cancel)
print(int(buttonReply))
if buttonReply == QMessageBox.Yes:
print('Yes clicked.')
if buttonReply == QMessageBox.No:
print('No clicked.')
if buttonReply == QMessageBox.Cancel:
print('Cancel')
可用的按钮有:
总览 | ||
---|---|---|
QMessageBox.Cancel |
QMessageBox.Ok |
QMessageBox.Help |
QMessageBox.Open |
QMessageBox.Save |
QMessageBox.SaveAll |
QMessageBox.Discard |
QMessageBox.Close |
QMessageBox.Apply |
QMessageBox.Reset |
QMessageBox.Yes |
QMessageBox.YesToAll |
QMessageBox.No |
QMessageBox.NoToAll |
QMessageBox.NoButton |
QMessageBox.RestoreDefaults |
QMessageBox.Abort |
QMessageBox.Retry |
QMessageBox.Ignore |
PyQt5 文本框示例
在本文中,您将学习如何在 PyQt5 中使用文本框。 该小部件称为QLineEdit
,并具有setText()
来设置文本框值的方法,以及text()
来获取值的方法。
我们可以使用resize(width, height)
方法设置文本框的大小。 可以使用move(x, y)
方法或使用网格布局来设置位置。
PyQt5 文本框
创建文本框非常简单:
self.textbox = QLineEdit(self)
self.textbox.move(20, 20)
self.textbox.resize(280,40)
PyQt5 文本框示例
下面的示例创建一个带有文本框的窗口。
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QPushButton, QAction, QLineEdit, QMessageBox
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot
class App(QMainWindow):
def __init__(self):
super().__init__()
self.title = 'PyQt5 textbox - pythonspot.com'
self.left = 10
self.top = 10
self.width = 400
self.height = 140
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
# Create textbox
self.textbox = QLineEdit(self)
self.textbox.move(20, 20)
self.textbox.resize(280,40)
# Create a button in the window
self.button = QPushButton('Show text', self)
self.button.move(20,80)
# connect button to function on_click
self.button.clicked.connect(self.on_click)
self.show()
@pyqtSlot()
def on_click(self):
textboxValue = self.textbox.text()
QMessageBox.question(self, 'Message - pythonspot.com', "You typed: " + textboxValue, QMessageBox.Ok, QMessageBox.Ok)
self.textbox.setText("")
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
PyQt5 菜单
要为 PyQt5 程序创建菜单,我们需要使用QMainWindow
。 这种类型的菜单在许多应用程序中都可见,并显示在窗口栏的正下方。 它通常具有文件和编辑子菜单。
可以使用menuBar()
方法创建顶部菜单。 子菜单添加了addMenu(name)
。示例:
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu('File')
editMenu = mainMenu.addMenu('Edit')
viewMenu = mainMenu.addMenu('View')
searchMenu = mainMenu.addMenu('Search')
toolsMenu = mainMenu.addMenu('Tools')
helpMenu = mainMenu.addMenu('Help')
可以将单个按钮添加到菜单中,如下所示:
exitButton = QAction(QIcon('exit24.png'), 'Exit', self)
exitButton.setShortcut('Ctrl+Q')
exitButton.setStatusTip('Exit application')
exitButton.triggered.connect(self.close)
fileMenu.addAction(exitButton)
PyQt5 菜单示例
完整代码:
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QPushButton, QAction
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot
class App(QMainWindow):
def __init__(self):
super().__init__()
self.title = 'PyQt5 menu - pythonspot.com'
self.left = 10
self.top = 10
self.width = 640
self.height = 400
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu('File')
editMenu = mainMenu.addMenu('Edit')
viewMenu = mainMenu.addMenu('View')
searchMenu = mainMenu.addMenu('Search')
toolsMenu = mainMenu.addMenu('Tools')
helpMenu = mainMenu.addMenu('Help')
exitButton = QAction(QIcon('exit24.png'), 'Exit', self)
exitButton.setShortcut('Ctrl+Q')
exitButton.setStatusTip('Exit application')
exitButton.triggered.connect(self.close)
fileMenu.addAction(exitButton)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
结果:
PyQt5 表格
在本文中,您将学习如何将表格与 PyQt5 结合使用。 您可以将一个或多个表格添加到任何 PyQt 应用程序或窗口。
表格可以具有多个行和列。 可以使用setRowCount()
和setColumnCount()
来指定。
要添加表格,您将需要导入QTableWidget
和QTableWidgetItem
。
示例
from PyQt5.QtWidgets import QTableWidget,QTableWidgetItem
使用以下命令创建一个表格:
self.tableWidget = QTableWidget()
# set row count
self.tableWidget.setRowCount(4)
# set column count
self.tableWidget.setColumnCount(2)
要添加单个单元格:
self.tableWidget.setItem(X,Y, QTableWidgetItem("TEXT"))
PyQt5 表格示例
完整的 PyQt5 表格代码如下:
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QAction, QTableWidget,QTableWidgetItem,QVBoxLayout
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'PyQt5 table - pythonspot.com'
self.left = 0
self.top = 0
self.width = 300
self.height = 200
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.createTable()
# Add box layout, add table to box layout and add box layout to widget
self.layout = QVBoxLayout()
self.layout.addWidget(self.tableWidget)
self.setLayout(self.layout)
# Show widget
self.show()
def createTable(self):
# Create table
self.tableWidget = QTableWidget()
self.tableWidget.setRowCount(4)
self.tableWidget.setColumnCount(2)
self.tableWidget.setItem(0,0, QTableWidgetItem("Cell (1,1)"))
self.tableWidget.setItem(0,1, QTableWidgetItem("Cell (1,2)"))
self.tableWidget.setItem(1,0, QTableWidgetItem("Cell (2,1)"))
self.tableWidget.setItem(1,1, QTableWidgetItem("Cell (2,2)"))
self.tableWidget.setItem(2,0, QTableWidgetItem("Cell (3,1)"))
self.tableWidget.setItem(2,1, QTableWidgetItem("Cell (3,2)"))
self.tableWidget.setItem(3,0, QTableWidgetItem("Cell (4,1)"))
self.tableWidget.setItem(3,1, QTableWidgetItem("Cell (4,2)"))
self.tableWidget.move(0,0)
# table selection change
self.tableWidget.doubleClicked.connect(self.on_click)
@pyqtSlot()
def on_click(self):
print("\n")
for currentQTableWidgetItem in self.tableWidget.selectedItems():
print(currentQTableWidgetItem.row(), currentQTableWidgetItem.column(), currentQTableWidgetItem.text())
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
PyQt5 标签
在本文中,您将学习将选项卡与 PyQt5 结合使用。 我们将首先显示完整的代码,然后进行解释。 PyQt5 有一个小部件来创建称为QTabWidget
的选项卡。QTabWidget
可以包含选项卡(QWidget
),这些选项卡上具有小部件,例如标签,按钮,图像等。
PyQt5 标签示例
完整 PyQt5 标签示例:
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, QWidget, QAction, QTabWidget,QVBoxLayout
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot
class App(QMainWindow):
def __init__(self):
super().__init__()
self.title = 'PyQt5 tabs - pythonspot.com'
self.left = 0
self.top = 0
self.width = 300
self.height = 200
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.table_widget = MyTableWidget(self)
self.setCentralWidget(self.table_widget)
self.show()
class MyTableWidget(QWidget):
def __init__(self, parent):
super(QWidget, self).__init__(parent)
self.layout = QVBoxLayout(self)
# Initialize tab screen
self.tabs = QTabWidget()
self.tab1 = QWidget()
self.tab2 = QWidget()
self.tabs.resize(300,200)
# Add tabs
self.tabs.addTab(self.tab1,"Tab 1")
self.tabs.addTab(self.tab2,"Tab 2")
# Create first tab
self.tab1.layout = QVBoxLayout(self)
self.pushButton1 = QPushButton("PyQt5 button")
self.tab1.layout.addWidget(self.pushButton1)
self.tab1.setLayout(self.tab1.layout)
# Add tabs to widget
self.layout.addWidget(self.tabs)
self.setLayout(self.layout)
@pyqtSlot()
def on_click(self):
print("\n")
for currentQTableWidgetItem in self.tableWidget.selectedItems():
print(currentQTableWidgetItem.row(), currentQTableWidgetItem.column(), currentQTableWidgetItem.text())
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
说明:
要将表添加到窗口,我们创建一个新类:
class MyTableWidget(QWidget)
我们通过为标签创建一个QTabWidget
和两个QWidget
来初始化标签屏幕。
self.tabs = QTabWidget()
self.tab1 = QWidget()
self.tab2 = QWidget()
self.tabs.resize(300,200)
然后,我们将这些选项卡添加到选项卡小部件中:
self.tabs.addTab(self.tab1,"Tab 1")
self.tabs.addTab(self.tab2,"Tab 2")
使用以下命令创建选项卡的内容:
self.tab1.layout = QVBoxLayout(self)
self.pushButton1 = QPushButton("PyQt5 button")
self.tab1.layout.addWidget(self.pushButton1)
self.tab1.setLayout(self.tab1.layout)
最后,我们将标签添加到小部件中:
self.layout.addWidget(self.tabs)
self.setLayout(self.layout)
不要忘记将您的自定义标签窗口小部件添加到窗口中:
self.table_widget = MyTableWidget(self)
self.setCentralWidget(self.table_widget)
PyQt5 水平布局
窗口可以包含小部件(按钮,文本字段,图像等)。 窗口小部件经常添加到布局中。 水平布局可用于在水平方向上(动态)添加小部件。
在本文中,我们将向您展示如何使用水平布局在水平方向上添加按钮。
水平布局示例
我们将显示整个代码,然后进行解释。
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout, QGroupBox, QDialog, QVBoxLayout
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot
class App(QDialog):
def __init__(self):
super().__init__()
self.title = 'PyQt5 layout - pythonspot.com'
self.left = 10
self.top = 10
self.width = 320
self.height = 100
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.createHorizontalLayout()
windowLayout = QVBoxLayout()
windowLayout.addWidget(self.horizontalGroupBox)
self.setLayout(windowLayout)
self.show()
def createHorizontalLayout(self):
self.horizontalGroupBox = QGroupBox("What is your favorite color?")
layout = QHBoxLayout()
buttonBlue = QPushButton('Blue', self)
buttonBlue.clicked.connect(self.on_click)
layout.addWidget(buttonBlue)
buttonRed = QPushButton('Red', self)
buttonRed.clicked.connect(self.on_click)
layout.addWidget(buttonRed)
buttonGreen = QPushButton('Green', self)
buttonGreen.clicked.connect(self.on_click)
layout.addWidget(buttonGreen)
self.horizontalGroupBox.setLayout(layout)
@pyqtSlot()
def on_click(self):
print('PyQt5 button click')
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
解释
我们首先在initUI()
方法中调用self.createHorizontalLayout()
方法。 在方法内部,我们创建了一个带有标题和水平布局的框:
self.horizontalGroupBox = QGroupBox("What is your favorite color?")
layout = QHBoxLayout()
我们创建小部件(在此示例中为QPushButtons
),并将它们一个接一个地添加到布局中:
buttonBlue = QPushButton('Blue', self)
buttonBlue.clicked.connect(self.on_click)
layout.addWidget(buttonBlue)
我们将标题框设置为包含水平布局:
self.horizontalGroupBox.setLayout(layout)
在initUI
方法中,我们将其添加到窗口中:
windowLayout = QVBoxLayout()
windowLayout.addWidget(self.horizontalGroupBox)
self.setLayout(windowLayout)
PyQt5 网格布局
PyQt5 支持网格布局,其名称为QGridLayout
。 可以在水平和垂直方向上将小部件添加到网格中。 带有小部件的网格布局示例如下所示:
PyQt5 网格布局示例:
下面的示例创建网格:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout, QGroupBox, QDialog, QVBoxLayout, QGridLayout
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot
class App(QDialog):
def __init__(self):
super().__init__()
self.title = 'PyQt5 layout - pythonspot.com'
self.left = 10
self.top = 10
self.width = 320
self.height = 100
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.createGridLayout()
windowLayout = QVBoxLayout()
windowLayout.addWidget(self.horizontalGroupBox)
self.setLayout(windowLayout)
self.show()
def createGridLayout(self):
self.horizontalGroupBox = QGroupBox("Grid")
layout = QGridLayout()
layout.setColumnStretch(1, 4)
layout.setColumnStretch(2, 4)
layout.addWidget(QPushButton('1'),0,0)
layout.addWidget(QPushButton('2'),0,1)
layout.addWidget(QPushButton('3'),0,2)
layout.addWidget(QPushButton('4'),1,0)
layout.addWidget(QPushButton('5'),1,1)
layout.addWidget(QPushButton('6'),1,2)
layout.addWidget(QPushButton('7'),2,0)
layout.addWidget(QPushButton('8'),2,1)
layout.addWidget(QPushButton('9'),2,2)
self.horizontalGroupBox.setLayout(layout)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
解释
我们通过以下方式导入gridlayout
和其他内容:
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout, QGroupBox, QDialog, QVBoxLayout, QGridLayout
在方法createGridLayout()
中,我们创建带有标题的网格并设置大小。
def createGridLayout(self):
self.horizontalGroupBox = QGroupBox("Grid")
layout = QGridLayout()
layout.setColumnStretch(1, 4)
layout.setColumnStretch(2, 4)
使用addWidget
layout.addWidget(Widget,X,Y)
最后,我们设置布局。
PyQT5 输入对话框
PyQt5 支持多个输入对话框,使用它们可以导入QInputDialog
。
from PyQt5.QtWidgets import QApplication, QWidget, QInputDialog, QLineEdit
PyQt5 输入对话框概述:
获取整数
使用QInputDialog.getInt()
获取整数:
def getInteger(self):
i, okPressed = QInputDialog.getInt(self, "Get integer","Percentage:", 28, 0, 100, 1)
if okPressed:
print(i)
参数顺序如下:自身,窗口标题,标签(在输入框之前),默认值,最小,最大和步长。
获得浮点
通过QInputDialog.getDouble()
获得双倍:
def getDouble(self):
d, okPressed = QInputDialog.getDouble(self, "Get double","Value:", 10.05, 0, 100, 10)
if okPressed:
print(d)
最后一个参数(10)是逗号后面的小数位数。
获取/选择项目
从下拉框中获取一个项目:
def getChoice(self):
items = ("Red","Blue","Green")
item, okPressed = QInputDialog.getItem(self, "Get item","Color:", items, 0, False)
if okPressed and item:
print(item)
获取字符串
使用QInputDialog.getText()
获取字符串
def getText(self):
text, okPressed = QInputDialog.getText(self, "Get text","Your name:", QLineEdit.Normal, "")
if okPressed and text != '':
print(text)
所有 PyQt5 输入对话框的示例
下面的完整示例:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QInputDialog, QLineEdit
from PyQt5.QtGui import QIcon
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'PyQt5 input dialogs - pythonspot.com'
self.left = 10
self.top = 10
self.width = 640
self.height = 480
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.getInteger()
self.getText()
self.getDouble()
self.getChoice()
self.show()
def getInteger(self):
i, okPressed = QInputDialog.getInt(self, "Get integer","Percentage:", 28, 0, 100, 1)
if okPressed:
print(i)
def getDouble(self):
d, okPressed = QInputDialog.getDouble(self, "Get double","Value:", 10.50, 0, 100, 10)
if okPressed:
print( d)
def getChoice(self):
items = ("Red","Blue","Green")
item, okPressed = QInputDialog.getItem(self, "Get item","Color:", items, 0, False)
if ok and item:
print(item)
def getText(self):
text, okPressed = QInputDialog.getText(self, "Get text","Your name:", QLineEdit.Normal, "")
if okPressed and text != '':
print(text)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
PyQt5 文件对话框
PyQt5 支持(本机)文件对话框:打开文件,打开文件和保存文件。 通过调用 PyQt5 中包含的功能,您将获得默认的文件对话框,而无需从头开始重新创建这些对话框。
需要导入QFileDialog
。
文件对话框示例
使用的方法是QFileDialog.getOpenFileName()
,QFileDialog.getOpenFileNames()
,QFileDialog.getSaveFileName()
。 使用方法参数可以指定默认目录,文件类型和默认文件名。
下面的代码将显示所有文件对话框:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QInputDialog, QLineEdit, QFileDialog
from PyQt5.QtGui import QIcon
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'PyQt5 file dialogs - pythonspot.com'
self.left = 10
self.top = 10
self.width = 640
self.height = 480
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.openFileNameDialog()
self.openFileNamesDialog()
self.saveFileDialog()
self.show()
def openFileNameDialog(self):
options = QFileDialog.Options()
options |= QFileDialog.DontUseNativeDialog
fileName, _ = QFileDialog.getOpenFileName(self,"QFileDialog.getOpenFileName()", "","All Files (*);;Python Files (*.py)", options=options)
if fileName:
print(fileName)
def openFileNamesDialog(self):
options = QFileDialog.Options()
options |= QFileDialog.DontUseNativeDialog
files, _ = QFileDialog.getOpenFileNames(self,"QFileDialog.getOpenFileNames()", "","All Files (*);;Python Files (*.py)", options=options)
if files:
print(files)
def saveFileDialog(self):
options = QFileDialog.Options()
options |= QFileDialog.DontUseNativeDialog
fileName, _ = QFileDialog.getSaveFileName(self,"QFileDialog.getSaveFileName()","","All Files (*);;Text Files (*.txt)", options=options)
if fileName:
print(fileName)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
PyQt5 图像
PyQt5(和 Qt)默认情况下支持图像。 在本文中,我们将向您展示如何向窗口添加图像。 可以使用QPixmap
类加载图像。
PyQt5 图像简介
将图像添加到 PyQt5 窗口就像创建标签并将图像添加到该标签一样简单。
label = QLabel(self)
pixmap = QPixmap('image.jpeg')
label.setPixmap(pixmap)
# Optional, resize window to image size
self.resize(pixmap.width(),pixmap.height())
这些是必需的导入:
from PyQt5.QtWidgets import QApplication, QWidget, QLabel
from PyQt5.QtGui import QIcon, QPixmap
PyQt5 加载图像(QPixmap
)
复制下面的代码并运行。 该映像应与程序位于同一目录中。
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel
from PyQt5.QtGui import QIcon, QPixmap
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'PyQt5 image - pythonspot.com'
self.left = 10
self.top = 10
self.width = 640
self.height = 480
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
# Create widget
label = QLabel(self)
pixmap = QPixmap('image.jpeg')
label.setPixmap(pixmap)
self.resize(pixmap.width(),pixmap.height())
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
Qt4 窗口
Ubuntu 上的 PyQt4 窗口
在本教程中,您将学习如何使用 PyQT4 创建图形 hello world 应用程序。
PyQT4 ,它是图形用户界面(GUI)编程的 Python 选项之一。
PyQt4 窗口示例:
该应用程序将创建一个可最小化,最大化和调整其大小的图形窗口。
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
import sys
from PyQt4.QtGui import *
# Create an PyQT4 application object.
a = QApplication(sys.argv)
# The QWidget widget is the base class of all user interface objects in PyQt4.
w = QWidget()
# Set window size.
w.resize(320, 240)
# Set window title
w.setWindowTitle("Hello World!")
# Show window
w.show()
sys.exit(a.exec_())
必须导入 PyQT4 模块,我们通过以下代码行进行导入:
from PyQt4.QtGui import *
我们使用QApplication()
创建 PyQT4 应用程序对象:
a = QApplication(sys.argv)
我们创建窗口(QWidget
),调整大小,设置标题并显示以下代码:
w = QWidget()
w.resize(320, 240)
w.setWindowTitle("Hello World!")
不要忘记显示窗口:
# Show window
w.show()
您可以下载 PyQt4 示例集合:下载 PyQT 代码(批量集合)
Qt4 按钮
PyQt4 按钮示例
PyQt4(Qt4)通过 QPushButton 小部件支持按钮。
我们扩展代码以在窗口中心显示一个按钮。
如果将鼠标悬停在该按钮上将显示一个工具提示,按下该按钮将关闭程序。
PyQt4 按钮示例
下面的示例在 PyQt4 窗口中添加了一个按钮。
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
import sys
from PyQt4.QtGui import *
# Create an PyQT4 application object.
a = QApplication(sys.argv)
# The QWidget widget is the base class of all user interface objects in PyQt4.
w = QWidget()
# Set window size.
w.resize(320, 240)
# Set window title
w.setWindowTitle("Hello World!")
# Add a button
btn = QPushButton('Hello World!', w)
btn.setToolTip('Click to quit!')
btn.clicked.connect(exit)
btn.resize(btn.sizeHint())
btn.move(100, 80)
# Show window
w.show()
sys.exit(a.exec_())
PyQt4 信号和槽
单击按钮应该可以执行某些操作。 为此,您必须使用信号和槽。
如果用户执行诸如单击按钮,在框中键入文本之类的操作,则小部件会发出信号。 信号可以与一个槽相连,该槽充当接收器并对其起作用。
import sys
from PyQt4.QtCore import pyqtSlot
from PyQt4.QtGui import *
# create our window
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle('Button click example @pythonspot.com')
# Create a button in the window
btn = QPushButton('Click me', w)
# Create the actions
@pyqtSlot()
def on_click():
print('clicked')
@pyqtSlot()
def on_press():
print('pressed')
@pyqtSlot()
def on_release():
print('released')
# connect the signals to the slots
btn.clicked.connect(on_click)
btn.pressed.connect(on_press)
btn.released.connect(on_release)
# Show the window and run the app
w.show()
app.exec_()
QT4 消息框
PyQT4 使用多种功能提供消息框功能。 PyQT4 中包含的 消息框是:问题,警告,错误,信息,批评和关于框。
PyQt4 消息框
下面的代码将显示一个带有两个按钮的消息框:
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
import sys
from PyQt4.QtGui import *
# Create an PyQT4 application object.
a = QApplication(sys.argv)
# The QWidget widget is the base class of all user interface objects in PyQt4.
w = QWidget()
# Show a message box
result = QMessageBox.question(w, 'Message', "Do you like Python?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if result == QMessageBox.Yes:
print('Yes.')
else:
print('No.')
# Show window
w.show()
sys.exit(a.exec_())
结果:
QT 问题消息框
PyQT4 提供了不同类型的消息框。
PyQT4 警告框
您可以使用以下代码行显示警告框:
QMessageBox.warning(w, "Message", "Are you sure you want to continue?")
PyQT4 信息框
我们可以使用QMessageBox.information()
显示一个信息框
QMessageBox.information(w, "Message", "An information messagebox @ pythonspot.com ")
结果:
QMessageBox
信息
PyQT4 错误框
如果您的应用程序出现问题,则可能需要显示一条错误消息。
QMessageBox.critical(w, "Message", "No disk space left on device.")
结果:
QMessagebox
PyQT4 关于框
我们已经在上面显示了问题框。
QMessageBox.about(w, "About", "An example messagebox @ pythonspot.com ")
结果
QT 消息框
PyQt4 的菜单
PyQT 菜单
PyQt4 菜单出现在窗口栏的顶部。 菜单使用户可以控制应用程序,并且通常位于窗口顶部。
QMainWindow
类创建主应用程序窗口。 此类具有一个名为menuBar()
的方法,该方法添加标题栏。
可以使用addMenu()
将菜单添加到标题栏。 在每个菜单内,您都可以使用addAction
方法添加命令。
PyQt4 菜单栏
此代码将为您的 qt4 应用添加菜单:
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
import sys
from PyQt4.QtGui import *
# Create an PyQT4 application object.
a = QApplication(sys.argv)
# The QWidget widget is the base class of all user interface objects in PyQt4.
w = QMainWindow()
# Set window size.
w.resize(320, 240)
# Set window title
w.setWindowTitle("Hello World!")
# Create main menu
mainMenu = w.menuBar()
mainMenu.setNativeMenuBar(False)
fileMenu = mainMenu.addMenu('&File')
# Add exit button
exitButton = QAction(QIcon('exit24.png'), 'Exit', w)
exitButton.setShortcut('Ctrl+Q')
exitButton.setStatusTip('Exit application')
exitButton.triggered.connect(w.close)
fileMenu.addAction(exitButton)
# Show window
w.show()
sys.exit(a.exec_())
QT4 小部件
我们有许多可通过 PyQT 访问的小部件。 其中包括:
- 文本框
- 组合框
- 日历
对于更多小部件,我们建议使用下一个教程中介绍的 GUI 创建工具。
文本框小部件
几乎每个应用程序中都存在输入字段。 在 PyQT4 中,可以使用QLineEdit()
函数创建输入字段。
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
import sys
from PyQt4.QtGui import *
# Create an PyQT4 application object.
a = QApplication(sys.argv)
# The QWidget widget is the base class of all user interface objects in PyQt4.
w = QMainWindow()
# Set window size.
w.resize(320, 100)
# Set window title
w.setWindowTitle("PyQT Python Widget!")
# Create textbox
textbox = QLineEdit(w)
textbox.move(20, 20)
textbox.resize(280,40)
# Show window
w.show()
sys.exit(a.exec_())
qt 文本框
组合框
组合框可用于从列表中选择一个项目。
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
import sys
from PyQt4.QtGui import *
# Create an PyQT4 application object.
a = QApplication(sys.argv)
# The QWidget widget is the base class of all user interface objects in PyQt4.
w = QMainWindow()
# Set window size.
w.resize(320, 100)
# Set window title
w.setWindowTitle("PyQT Python Widget!")
# Create combobox
combo = QComboBox(w)
combo.addItem("Python")
combo.addItem("Perl")
combo.addItem("Java")
combo.addItem("C++")
combo.move(20,20)
# Show window
w.show()
sys.exit(a.exec_())
qt 组合框
日历小部件
PyQT4 库有一个日历小部件,您可以使用QCalendarWidget()
调用来创建它。
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
import sys
from PyQt4.QtGui import *
# Create an PyQT4 application object.
a = QApplication(sys.argv)
# The QWidget widget is the base class of all user interface objects in PyQt4.
w = QMainWindow()
# Set window size.
w.resize(320, 240)
# Set window title
w.setWindowTitle("PyQT Python Widget!")
# Create calendar
cal = QCalendarWidget(w)
cal.setGridVisible(True)
cal.move(0, 0)
cal.resize(320,240)
# Show window
w.show()
sys.exit(a.exec_())
结果:
qt 日历
PyQt4 文本框
PyQt4 文本框示例
在本文中,您将学习如何使用 PyQt4 与文本框进行交互。
如果要在文本框(QLineEdit
)中显示文本,则可以使用setText()
方法。
PyQt4 QLineEdit
如果按下按钮,下面的文本框示例将更改文本。
import sys
from PyQt4.QtCore import pyqtSlot
from PyQt4.QtGui import *
# create our window
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle('Textbox example @pythonspot.com')
# Create textbox
textbox = QLineEdit(w)
textbox.move(20, 20)
textbox.resize(280,40)
# Set window size.
w.resize(320, 150)
# Create a button in the window
button = QPushButton('Click me', w)
button.move(20,80)
# Create the actions
@pyqtSlot()
def on_click():
textbox.setText("Button clicked.")
# connect the signals to the slots
button.clicked.connect(on_click)
# Show the window and run the app
w.show()
app.exec_()
使用以下行创建文本字段:
textbox = QLineEdit(w)
textbox.move(20, 20)
textbox.resize(280,40)
该按钮(来自屏幕截图)由以下部分制成:
button = QPushButton('Click me', w)
我们通过以下方式将按钮连接到on_click
函数:
# connect the signals to the slots
button.clicked.connect(on_click)
此函数使用setText()
设置文本框。
QT4 表格
我们可以使用QTableWidget
来显示表格,QTableWidget
是 PyQt 模块的一部分。 我们设置标题,行数,列数并添加数据。
Qt4 表格示例
下面的例子:
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys
def main():
app = QApplication(sys.argv)
table = QTableWidget()
tableItem = QTableWidgetItem()
# initiate table
table.setWindowTitle("QTableWidget Example @pythonspot.com")
table.resize(400, 250)
table.setRowCount(4)
table.setColumnCount(2)
# set data
table.setItem(0,0, QTableWidgetItem("Item (1,1)"))
table.setItem(0,1, QTableWidgetItem("Item (1,2)"))
table.setItem(1,0, QTableWidgetItem("Item (2,1)"))
table.setItem(1,1, QTableWidgetItem("Item (2,2)"))
table.setItem(2,0, QTableWidgetItem("Item (3,1)"))
table.setItem(2,1, QTableWidgetItem("Item (3,2)"))
table.setItem(3,0, QTableWidgetItem("Item (4,1)"))
table.setItem(3,1, QTableWidgetItem("Item (4,2)"))
# show table
table.show()
return app.exec_()
if __name__ == '__main__':
main()
结果:
PyQT 表格提示
QT4 标签
选项卡在图形应用程序中非常有用。 它们出现在网络浏览器,文本编辑器和任何其他应用中。 要创建选项卡式窗口,您需要调用QTabWidget()
函数。 每个选项卡都是您之前看到的QWidget()
。 您可以使用以下函数将QWidget
与QTabWidget
连接:
tabs.addTab(tab1,"Tab 1")
其中第一个参数是选项卡对象,第二个参数是显示在屏幕上的名称。 我们在第一个标签(QWidget
)中添加了一些按钮。
示例代码:
from PyQt4 import QtGui
from PyQt4 import QtCore
import sys
def main():
app = QtGui.QApplication(sys.argv)
tabs = QtGui.QTabWidget()
# Create tabs
tab1 = QtGui.QWidget()
tab2 = QtGui.QWidget()
tab3 = QtGui.QWidget()
tab4 = QtGui.QWidget()
# Resize width and height
tabs.resize(250, 150)
# Set layout of first tab
vBoxlayout = QtGui.QVBoxLayout()
pushButton1 = QtGui.QPushButton("Start")
pushButton2 = QtGui.QPushButton("Settings")
pushButton3 = QtGui.QPushButton("Stop")
vBoxlayout.addWidget(pushButton1)
vBoxlayout.addWidget(pushButton2)
vBoxlayout.addWidget(pushButton3)
tab1.setLayout(vBoxlayout)
# Add tabs
tabs.addTab(tab1,"Tab 1")
tabs.addTab(tab2,"Tab 2")
tabs.addTab(tab3,"Tab 3")
tabs.addTab(tab4,"Tab 4")
# Set title and show
tabs.setWindowTitle('PyQt QTabWidget @ pythonspot.com')
tabs.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
结果:
PyQT 标签
QT4 进度条
在本文中,我们将演示如何使用进度条小部件。 进度条与其他小部件的不同之处在于,它会及时更新。
QT4 进度条示例
让我们从代码开始:
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.QtCore import pyqtSlot,SIGNAL,SLOT
class QProgBar(QProgressBar):
value = 0
@pyqtSlot()
def increaseValue(progressBar):
progressBar.setValue(progressBar.value)
progressBar.value = progressBar.value+1
# Create an PyQT4 application object.
a = QApplication(sys.argv)
# The QWidget widget is the base class of all user interface objects in PyQt4.
w = QWidget()
# Set window size.
w.resize(320, 240)
# Set window title
w.setWindowTitle("PyQT4 Progressbar @ pythonspot.com ")
# Create progressBar.
bar = QProgBar(w)
bar.resize(320,50)
bar.setValue(0)
bar.move(0,20)
# create timer for progressBar
timer = QTimer()
bar.connect(timer,SIGNAL("timeout()"),bar,SLOT("increaseValue()"))
timer.start(400)
# Show window
w.show()
sys.exit(a.exec_())
实例bar
(QProgBar
类的)用于保存进度条的值。 我们调用函数setValue()
来更新其值。 给定参数w
将其附加到主窗口。 然后,将其移动到屏幕上的位置(0, 20)
,并为其指定宽度和高度。
为了及时更新进度条,我们需要一个QTimer()
。 我们将小部件与计时器连接起来,计时器将调用函数gainValue()
。 我们将计时器设置为每 400 毫秒重复一次函数调用。 您还会看到单词SLOT
和SIGNAL
。 如果用户执行诸如单击按钮,在框中键入文本之类的操作,则该小部件会发出信号。 该信号没有任何作用,但可用于连接一个槽,该槽充当接收器并对其起作用。
结果:
PyQT 进度条
QT4 像素图(图像)
在本文中,我们将演示如何在 PyQT 窗口中加载和显示图像。 我们可以使用像素图小部件在 PyQT 窗口中显示图像。
在 PyQt4 窗口中加载的图像。
介绍
Pixmap
的构造函数将图像路径作为参数:
pixmap = QPixmap(os.getcwd() + '/logo.png')
该映像必须与程序位于同一目录中。QPixmap
小部件支持 png 和 jpeg。 下面的示例代码。
PyQT 在像素图中加载图像
我们像以前一样创建了一个标准的QWidget
。 然后,在其中添加QPixmap
小部件以加载图像。像素图贴在绘制到屏幕上的标签上。
import os
import sys
from PyQt4.QtGui import *
# Create window
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("PyQT4 Pixmap @ pythonspot.com ")
# Create widget
label = QLabel(w)
pixmap = QPixmap(os.getcwd() + '/logo.png')
label.setPixmap(pixmap)
w.resize(pixmap.width(),pixmap.height())
# Draw window
w.show()
app.exec_()
结果:
pyqt Pixmap
QT4 文件对话框
在这个简短的教程中,您将学习如何创建文件对话框并加载其文件内容。 使用文件访问的许多应用程序都需要文件对话框。
文件对话框示例
要在 PyQT 中获取文件名(而非文件数据),可以使用以下行:
filename = QFileDialog.getOpenFileName(w, 'Open File', '/')
如果您使用的是 Microsoft Windows,请使用
filename = QFileDialog.getOpenFileName(w, 'Open File', 'C:\')
下面的示例(包括加载文件数据):
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
import sys
from PyQt4.QtGui import *
# Create an PyQT4 application object.
a = QApplication(sys.argv)
# The QWidget widget is the base class of all user interface objects in PyQt4.
w = QWidget()
# Set window size.
w.resize(320, 240)
# Set window title
w.setWindowTitle("Hello World!")
# Get filename using QFileDialog
filename = QFileDialog.getOpenFileName(w, 'Open File', '/')
print(filename)
# print file contents
with open(filename, 'r') as f:
print(f.read())
# Show window
w.show()
sys.exit(a.exec_())
结果(输出可能因您的操作系统而异):
PyQt 文件打开对话框
PyQt4 GUI 教程
原文: https://pythonspot.com/building-an-application-gui-with-pyqt-beginners-tutorial/
在本教程中,我们将教您如何使用 PyQT4 创建图形应用程序。 这可以在支持 PyQT4 的任何平台上使用,包括 Windows,Linux,UNIX,Android,OS X 和 iOS。
PyQt4 安装
PyQt 不包括 Qt 本身-您可能必须单独获得它。PyQt 的主页是 https://www.riverbankcomputing.com/software/pyqt/。
您将需要安装一些软件包:
sudo pip install pyqt
sudo apt-get install qt4-designer
sudo apt-get install pyqt4-dev-tools
sudo apt-get install python-kde4
如果找不到python-kde4
,请更新您的存储库以找到它。 如果您使用的是 Ubuntu,请使用此链接。
构建一个 PyQT4 GUI
现在我们可以使用 QT Designer 应用程序。 它使我们不必编写许多编写 HTML 时可能习惯的布局代码。 从应用程序菜单中启动qt4-designer
。QT Designer 应用程序将出现。
QT Designer
按不带按钮的对话框,然后按创建。 现在,您可以将任何组件从窗口小部件框拖动到表单。 简单的拖放。 我们添加了一个按钮,标签和一个像素图。 (我从网上拍摄了一张随机图作为像素图)
QT KDE 对话框
我们的窗口如上图所示。 按“Form > Viewcode”。 我们将在 C++ 中得到一个带有表单代码的弹出框! 很好,但是我们需要 Python 代码。 按“文件 > 另存为 > form.ui
”。
文件test.ui
包含以 XML 格式描述的表单。 (您可以在文本编辑器中查看它)打开控制台并键入:
pyuic4 form.ui > form.py
运行文件没有任何作用。 创建一个名为gui.py
的新文件
粘贴以下代码:
import sys
from PyQt4 import QtCore, QtGui
from form import Ui_Dialog
class MyDialog(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyDialog()
myapp.show()
sys.exit(app.exec_())
运行:
python gui.py
这将打开我们的图形界面。 按下“确定”按钮将仅关闭该应用程序。
PyQt 窗口和QButton
我们想在按下 OK 按钮时添加一些动作。 我们将以下三行添加到代码中:
self.ui.pushButton.clicked.connect(self.OK)
def OK(self):
print 'OK pressed.'
pyqt4 应用示例
您可能会喜欢:使用 PyQt4 创建 Web 浏览器或 PyQT4 概述
QML 和 PyQT:创建 GUI(教程)
原文: https://pythonspot.com/qml-and-pyqt-creating-a-gui-tutorial/
如果您尚未完成我们的第一个 PyQT 教程,则应该这样做,这很有趣! 在本教程中,我们将使用 PyQT4 和用户界面标记语言,该语言描述图形用户界面和控件。
QML 和 PyQT
用户界面标记和语言代码的摘录可能类似于:
Rectangle {
id: simplebutton
color: "grey"
width: 150; height: 75
本质上,该语言告诉界面应该是什么样。 我们将使用的语言称为 QML。
QTCreator
启动一个名为 QTCreator 的程序。 本教程将以图形化方式帮助您完成整个过程。 只需在终端中键入qtcreator
或从菜单列表中启动它即可。 该屏幕应弹出:
QTCreator
创建一个 GUI
按新建项目按钮。 从下面的菜单中选择“QT 快速应用程序”。最后按右下角的选择。
QT Quick
将会出现一个新的弹出窗口:
kde 创建
输入名称和有效路径以保存您的项目。 然后按下一步。 从菜单列表中选择 QT Quick 2.0 。 按下一步。 按完成。 立即出现以 QML 语言定义的用户界面。
QT Quick
像所有伟大的程序员一样,我们将以最懒惰的方式解决问题。 无需手动输入所有 QML 代码,我们将按下屏幕左侧的设计按钮。 现在将出现一个拖放屏幕。
拖放
我们将图像拖到该区域上,然后选择右侧的源。 保存项目。 打开终端并找到您刚创建的 qml 文件。 或者,您可以简单地将代码复制到编辑框中,然后将其保存到.qml
文件中。 输入命令:
qmlviewer main.qml
这将显示 qml 文件中定义的窗口,没有任何功能。 它只是界面的查看器。 然后,我们创建一些代码来加载此 QML 定义:
import sys
from PyQt4.QtCore import QDateTime, QObject, QUrl, pyqtSignal
from PyQt4.QtGui import QApplication
from PyQt4.QtDeclarative import QDeclarativeView
app = QApplication(sys.argv)
# Create the QML user interface.
view = QDeclarativeView()
view.setSource(QUrl('main.qml'))
view.setResizeMode(QDeclarativeView.SizeRootObjectToView)
view.setGeometry(100, 100, 400, 240)
view.show()
app.exec_()
最后,我们将第一行main.qml
修改为:
import Qt 4.7
仅仅是因为我们的 QtQuick 不见了。运行:
python run.py
现在将显示 QML 定义的用户界面:
QML 和 PyQT
所有代码都是 PyQT ,因此您可以像上一教程中那样添加代码。 这是使用 PyQT 创建图形界面的两种方法。 与在上一教程中使用 QT 创建 GUI 的方法相比,该方法可能更宽松地与代码耦合。 尽管两者都是有效的方法。
您可能会喜欢:PyQT4 GUI 应用程序或 PyQt4 教程
Tk 窗口和按钮
带有onClick
事件的 Tk 按钮
要创建带有按钮的 Tkinter 窗口,请使用以下示例。 程序进入mainloop()
,等待事件(用户操作)。 我们定义具有回调函数callback()
的按钮。master
是根窗口,您的按钮将出现在该窗口中。
from Tkinter import *
master = Tk()
def callback():
print "click!"
b = Button(master, text="OK", command=callback)
b.pack()
mainloop()
tk 按钮
Tk 图像按钮
如果需要图像按钮,请使用PhotoImage
类。 我们使用函数minsize()
和geometry()
设置窗口的大小和最小大小。 例:
from Tkinter import *
master = Tk()
master.minsize(300,100)
master.geometry("320x100")
def callback():
print "click!"
photo=PhotoImage(file="add.png")
b = Button(master,image=photo, command=callback, height=50, width=150)
b.pack()
mainloop()
结果:
tk 图像按钮
带有文本标签的 Tk 图像按钮
如果需要图像和文本,只需添加参数compound = LEFT
。
from Tkinter import *
master = Tk()
master.minsize(300,100)
master.geometry("320x100")
def callback():
print "click!"
photo=PhotoImage(file="add.png")
b = Button(master,image=photo, text="OK", command=callback, height=50, width=150, compound=LEFT)
b.pack()
mainloop()
结果:
带有图像和文本的 tk 按钮
按钮位置
如果要将按钮放置在坐标上,请不要使用pack()
函数,而要使用place(x, y)
函数,如下例所示:
from Tkinter import *
master = Tk()
master.minsize(300,100)
master.geometry("320x100")
def callback():
print "click!"
photo=PhotoImage(file="add.png")
b = Button(master,image=photo, text="OK", command=callback, height=50, width=150, compound=LEFT)
b.place(x = 20, y = 20)
mainloop()
结果:
tk 按钮位置
Tk 菜单栏
Tkinter 工具箱包含所有用于创建图形应用程序的基本小部件。 几乎每个应用程序都有一个主菜单。 与预期的一样,Tkinter 支持将主菜单添加到您的应用程序窗口。
下面的屏幕截图演示了基于 Tkinter 的菜单:
Tkinter 菜单
Tkinter 菜单栏
您可以使用以下代码通过 Tkinter 创建一个简单菜单。 每个选项(新建,打开,保存..)都应具有自己的回调。
from Tkinter import *
def donothing():
x = 0
root = Tk()
menubar = Menu(root)
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label="New", command=donothing)
filemenu.add_command(label="Open", command=donothing)
filemenu.add_command(label="Save", command=donothing)
filemenu.add_separator()
filemenu.add_command(label="Exit", command=root.quit)
menubar.add_cascade(label="File", menu=filemenu)
helpmenu = Menu(menubar, tearoff=0)
helpmenu.add_command(label="Help Index", command=donothing)
helpmenu.add_command(label="About...", command=donothing)
menubar.add_cascade(label="Help", menu=helpmenu)
root.config(menu=menubar)
root.mainloop()
我们通过调用创建菜单栏:
menubar = Menu(root)
其中root
是Tk()
对象。
菜单栏可能包含零个或多个子菜单,例如文件菜单,编辑菜单,视图菜单,工具菜单等。
可以使用相同的Menu()
调用创建子菜单,其中第一个参数是要附加到的菜单栏。
filemenu = Menu(menubar, tearoff=0)
menu = Menu(menubar, tearoff=0)
可以使用add_command()
方法将各个选项添加到这些子菜单中:
filemenu.add_command(label="New", command=donothing)
filemenu.add_command(label="Open", command=donothing)
filemenu.add_command(label="Save", command=donothing)
在该示例中,我们创建了回调函数donothing()
并将每个命令链接到它以简化操作。 使用add_comment()
函数添加一个选项。 我们调用add_cascade()
将此菜单列表添加到特定列表。
Tk 小部件
Tkinter 有几个小部件,包括:
- 标签
- 编辑文字
- 图片
- 按钮(之前讨论过)
在本文中,我们将展示如何使用其中的一些 Tkinter 小部件。 请记住,Python 2.x 和 3.x 的 Tkinter 略有不同
标签
要创建标签,我们只需调用Label()
类并将其打包。padx
和pady
是水平和垂直填充。
from Tkinter import *
root = Tk()
root.title('Python Tk Examples @ pythonspot.com')
Label(root, text='Python').pack(pady=20,padx=50)
root.mainloop()
EditText
(条目小部件)
要获取用户输入,可以使用条目小部件。
from Tkinter import *
root = Tk()
root.title('Python Tk Examples @ pythonspot.com')
var = StringVar()
textbox = Entry(root, textvariable=var)
textbox.focus_set()
textbox.pack(pady=10, padx=10)
root.mainloop()
结果:
tk 条目
图像
Tk 具有一个小部件来显示图像,即PhotoImage
。 加载图像非常容易:
from Tkinter import *
import os
root = Tk()
img = PhotoImage(file="logo2.png")
panel = Label(root, image = img)
panel.pack(side = "bottom", fill = "both", expand = "yes")
root.mainloop()
结果:
python tk 图像
GUI 编辑器
Tkinter GUI 编辑器的概述可以在这里找到: http://wiki.tcl.tk/4056
TkInter 消息框
Tkinter tkMessageBox 具有多种显示消息框的方法。
适用于 Python 2.7 的 Tkinter 和 Python 3 之间略有不同。 要找到您的 Python 版本,请尝试以下命令之一:
python --version
python3 --version
Tkinter 消息框
TkMessage
框显示一个简约的 TkInter 对话框。
Tk 消息框对话框
Tkinter 包括其他几个消息框:
showerror()
showwarning()
showinfo()
Python 3.x
import tkinter
from tkinter import messagebox
# hide main window
root = tkinter.Tk()
root.withdraw()
# message box display
messagebox.showerror("Error", "Error message")
messagebox.showwarning("Warning","Warning message")
messagebox.showinfo("Information","Informative message")
Python 2.7
import Tkinter
import tkMessageBox
# An error box
tkMessageBox.showerror("Error","No disk space left on device")
# A warning box
tkMessageBox.showwarning("Warning","Could not start service")
# An information box
tkMessageBox.showinfo("Information","Created in Python.")
您可能会喜欢: Tkinter 问题对话框或更多 Tkinter
Tkinter tkFileDialog
模块
tkFileDialog
是具有打开和保存对话框功能的模块。 无需自己在 Tkinter GUI 中实现。
概述
文件对话框的概述:
Tkinter 打开文件
askopenfilename
函数创建文件对话框对象。 扩展名显示在表格的底部(文件类型)。 下面的代码将仅显示对话框并返回文件名。 如果用户按下取消,则文件名为空。 在 Windows 计算机上,将initialdir
更改为"C:\"
。
Python 2.7 版本:
函数 | 参数 | 目的 |
---|---|---|
.askopenfilename |
目录,标题,扩展名 | 打开文件:要求选择现有文件的对话框。 |
.asksaveasfilename |
目录,标题,扩展名 | 保存文件:要求创建或替换文件的对话框。 |
.askdirectory |
没有 | 打开目录 |
from Tkinter import *from Tkinter import *
import Tkinter, Tkconstants, tkFileDialog
root = Tk()
root.filename = tkFileDialog.askopenfilename(initialdir = "/",title = "Select file",filetypes = (("jpeg files","*.jpg"),("all files","*.*")))
print (root.filename)
Python 3 版本:
from tkinter import filedialog
from tkinter import *
root = Tk()
root.filename = filedialog.askopenfilename(initialdir = "/",title = "Select file",filetypes = (("jpeg files","*.jpg"),("all files","*.*")))
print (root.filename)
这是一个示例(在 Linux 上):
Tkinter tkfiledialog askopenfilename
Tkinter 保存文件
asksaveasfilename
函数使用保存文件对话框提示用户。
Python 2.7 版本
from Tkinter import *
import Tkinter, Tkconstants, tkFileDialog
root = Tk()
root.filename = tkFileDialog.asksaveasfilename(initialdir = "/",title = "Select file",filetypes = (("jpeg files","*.jpg"),("all files","*.*")))
print (root.filename)
Python 3 版本
from tkinter import filedialog
from tkinter import *
root = Tk()
root.filename = filedialog.asksaveasfilename(initialdir = "/",title = "Select file",filetypes = (("jpeg files","*.jpg"),("all files","*.*")))
print (root.filename)
Tkinter 打开目录
askdirectory
为用户提供了用于选择目录的弹出窗口。
Python 2.7 版本
from Tkinter import *
import Tkinter, Tkconstants, tkFileDialog
root = Tk()
root.directory = tkFileDialog.askdirectory()
print (root.directory)
tkinter askdirectory
Tk 下拉示例
Tkinter 支持下拉菜单。 这类似于操作系统上的标准组合框。
该小部件称为OptionMenu
,所需的参数为:帧,tk 变量和带有选择项的字典。
Tkinter 下拉示例
下面的示例创建一个带有组合框的 Tkinter 窗口。
from Tkinter import *
import Tkinter as ttk
from ttk import *
root = Tk()
root.title("Tk dropdown example")
# Add a grid
mainframe = Frame(root)
mainframe.grid(column=0,row=0, sticky=(N,W,E,S) )
mainframe.columnconfigure(0, weight = 1)
mainframe.rowconfigure(0, weight = 1)
mainframe.pack(pady = 100, padx = 100)
# Create a Tkinter variable
tkvar = StringVar(root)
# Dictionary with options
choices = { 'Pizza','Lasagne','Fries','Fish','Potatoe'}
tkvar.set('Pizza') # set the default option
popupMenu = OptionMenu(mainframe, tkvar, *choices)
Label(mainframe, text="Choose a dish").grid(row = 1, column = 1)
popupMenu.grid(row = 2, column =1)
# on change dropdown value
def change_dropdown(*args):
print( tkvar.get() )
# link function to change dropdown
tkvar.trace('w', change_dropdown)
root.mainloop()
首先创建一个 Tk 对象,并将其传递给使用Frame()
创建的 tkinter 框架
root = Tk()
root.title("Tk dropdown example")
mainframe = Frame(root)
将一个网格添加到框架,该框架将容纳组合框。
mainframe.grid(column=0,row=0, sticky=(N,W,E,S) )
mainframe.columnconfigure(0, weight = 1)
mainframe.rowconfigure(0, weight = 1)
mainframe.pack(pady = 100, padx = 100)
弹出菜单包含在变量选项中定义的选项列表。 使用以下行创建一个 Tkinter 变量:
tkvar = StringVar(root)
变量的默认值是使用.set()
方法设置的。 我们使用以下方法创建 Tkinter 组合框:
popupMenu = OptionMenu(mainframe, tkvar, *choices)
并将回调方法change_dropdown
链接到此组合框。
wxPython 窗口
wxPython 是用于 Python 编程语言的 GUI 工具箱。 wxPython 可用于创建图形用户界面(GUI)。
用 wxPython 制作的应用程序在所有平台上都有本机外观。 与具有自定义 QT 或 Tk 外观的 QT 或 Tk 不同,该应用程序将显示为本机应用程序。 它可以在所有主要的桌面平台上运行。
当前支持的操作系统是 Microsoft Windows(32 位),大多数 Unix 或类 Unix 系统以及 Macintosh OSX。
wxPython 模块基于 C++ GUI 库 wxWidgets。
wxPython 窗口
要使用 wxPython 打开窗口,请运行以下代码:
#!/usr/bin/python
import wx
app = wx.App()
frame = wx.Frame(None, -1, 'win.py')
frame.Show()
app.MainLoop()
wx.App()
行创建一个应用程序对象。 每个 wx 程序都需要具有一个.App()
对象。
wx.Frame()
方法返回一个可以包含小部件的新窗口。
app.Mainloop()
将应用程序置于主循环中并侦听事件。
窗口大小和位置
您可以使用SetDimensions()
函数设置位置和大小:
#!/usr/bin/python
import wx
app = wx.App()
frame = wx.Frame(None, -1, 'win.py')
frame.SetDimensions(0,0,640,480)
frame.Show()
app.MainLoop()
该函数的参数为:x
(左),y
(上),宽度和高度。 该功能不仅可以设置屏幕分辨率,还可以设置屏幕上的位置。
将窗口居中
要将窗口置于屏幕调用的中心:
frame.Centre()
wxPython 按钮
要创建按钮,只需调用wx.Button()
。 使用wx.Button()
创建按钮时,将面板解析为第一个参数很重要。 我们将其附加到面板上,因为将其附加到框架上将使其全屏显示。
面板使您可以选择将小部件放置在窗口中的任何位置。 参数(10, 10)
是面板上的位置。id
参数是必需的,但它等于-1
(wx.ID_ANY == -1
)。 第三个参数是按钮上的文本。
您可以使用下面的代码在 wxPython 中创建一个按钮:
#!/usr/bin/python
import wx
def onButton(event):
print "Button pressed."
app = wx.App()
frame = wx.Frame(None, -1, 'win.py')
frame.SetDimensions(0,0,200,50)
panel = wx.Panel(frame, wx.ID_ANY)
button = wx.Button(panel, wx.ID_ANY, 'Test', (10, 10))
button.Bind(wx.EVT_BUTTON, onButton)
frame.Show()
frame.Centre()
app.MainLoop()
如果按下按钮,则调用onButton()
函数。 我们将其与button.Bind(wx.EVT_BUTTON, onButton)
绑定(连接)。
输出:
使用 wxPython 创建的按钮
按钮上的图像
wxPython 支持在按钮上使用图像。 只需稍作更改即可在按钮上显示图像。 虽然该函数称为wx.BitmapButton
,但它支持其他图像格式。
bmp = wx.Bitmap("call-start.png", wx.BITMAP_TYPE_ANY)
button = wx.BitmapButton(panel, id=wx.ID_ANY, bitmap=bmp,
size=(bmp.GetWidth()+10, bmp.GetHeight()+10))
第一行加载图像,第二行创建按钮。
完整代码:
#!/usr/bin/python
import wx
def onButton(event):
print "Button pressed."
app = wx.App()
frame = wx.Frame(None, -1, 'win.py')
frame.SetDimensions(0,0,200,70)
panel = wx.Panel(frame, wx.ID_ANY)
bmp = wx.Bitmap("call-start.png", wx.BITMAP_TYPE_ANY)
button = wx.BitmapButton(panel, id=wx.ID_ANY, bitmap=bmp,
size=(bmp.GetWidth()+10, bmp.GetHeight()+10))
button.Bind(wx.EVT_BUTTON, onButton)
button.SetPosition((10,10))
frame.Show()
frame.Centre()
app.MainLoop()
输出:
wxButton
wxPython 对话框
要使用对话框,wxPython 仅需要几行代码。 我们将在下面演示。 我们将讨论信息对话框,简单对话框,错误对话框,警告对话框等。
信息对话框
信息对话框可以用一行代码显示:
import wx
app = wx.App()
wx.MessageBox('Pythonspot wxWidgets demo', 'Info', wx.OK | wx.ICON_INFORMATION)
第一个参数是要显示的实际文本。 第二个是标题,最后一个参数告诉 wx 显示信息图标和按钮。
输出:
wx 对话框
更多对话框:警告对话框,错误对话框和默认对话框
通过修改参数,您可以轻松创建其他类型的模拟日志。 下面的例子:
import wx
app = wx.App()
# simple dialog
wx.MessageBox('A dialog', 'Title', wx.OK)
# warning dialog
wx.MessageBox('Operation could not be completed', 'Warning', wx.OK | wx.ICON_WARNING)
# error dialog
wx.MessageBox('Operation could not be completed', 'Error', wx.OK | wx.ICON_ERROR)
输出(仅对话框之一):
wx 对话框
问题对话框
Wx 可用于创建问题对话框(是/否)。 示例代码:
import wx
app = wx.App()
dlg = wx.MessageDialog(None, "Do you want to update?",'Updater',wx.YES_NO | wx.ICON_QUESTION)
result = dlg.ShowModal()
if result == wx.ID_YES:
print "Yes pressed"
else:
print "No pressed"
输出:
wx 对话框
wxPython 文件对话框
几乎每个可以打开一个或多个文件的桌面应用程序都有一个文件对话框。
创建一个打开的文件对话框似乎是一个非常复杂的窗口:它包含按钮,位置,标签和许多其他小部件。 而且,此打开文件对话框的外观在每个平台上都不同:Mac OS,Windows 等。
在 wxPython 的模块配备了开放式的文件对话框,可以用几个函数的调用来创建。
wxPython 文件打开对话框
wxPython 文件对话框
下面的示例使用 wxPython 创建一个具有本机外观的文件对话框:
#!/usr/bin/python
import wx
def onButton(event):
print "Button pressed."
app = wx.App()
frame = wx.Frame(None, -1, 'win.py')
frame.SetDimensions(0,0,200,50)
# Create open file dialog
openFileDialog = wx.FileDialog(frame, "Open", "", "",
"Python files (*.py)|*.py",
wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
openFileDialog.ShowModal()
print(openFileDialog.GetPath())
openFileDialog.Destroy()
要使用 wxPython 创建文件对话框,我们可以简单地调用wx.FileDialog()
。 此方法的定义是:(parent, messgae, defaultDir, defaultFile, pattern, style, pos)
。我们用以下参数调用此方法:
wx.FileDialog(frame, "Open", "", "","Python files (*.py)|*.py",wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
(未指定默认目录或默认文件)。
showModal()
方法显示窗口:
openFileDialog.ShowModal()
如果选择一个,则命令openFileDialog.GetPath()
返回文件的完整路径。
wxPython 输入对话框
输入对话框可让您的用户给您反馈或输入。 它们偶尔会出现在桌面应用程序中。
wxPython 支持输入对话框,它们包含在框架中。 典型的 wxPython 对话框如下所示:
用 wxPython 创建的输入对话框
wxPython 输入对话框
下面的示例代码使用 wxPython 创建一个输入对话框:
#!/usr/bin/python
import wx
def onButton(event):
print "Button pressed."
app = wx.App()
frame = wx.Frame(None, -1, 'win.py')
frame.SetDimensions(0,0,200,50)
# Create text input
dlg = wx.TextEntryDialog(frame, 'Enter some text','Text Entry')
dlg.SetValue("Default")
if dlg.ShowModal() == wx.ID_OK:
print('You entered: %s\n' % dlg.GetValue())
dlg.Destroy()
可以使用以下函数将 wxPython 文本框添加到窗口:
wx.TextEntryDialog(frame, 'Enter some text','Text Entry')
其中第一个参数是框架,第二个参数是标签,最后一个参数是窗口标题。
下面的函数显示对话框,并等待用户按下按钮之一:
dlg.ShowModal()
您可以通过选择以下按钮之一来按下按钮:
wx.OK
wx.CANCEL
(结果是其中之一)
给出输入后,可以使用dlg.GetValue()
函数获取输入文本。
wxPython 选项卡
尽管出于简单性原因,我们并未在 wxPython 系列中大量使用面向对象,但是我们无法解决它。 在本教程中,您将学习如何使用 wxPython 创建选项卡界面。
Mainframe
类创建框架,就像前面的示例一样。 其他类别是选项卡的内容。 我们在主框架中创建一个面板和笔记本(标签夹)。 然后我们创建标签对象:
tab1 = TabOne(nb)
tab2 = TabTwo(nb)
...
我们使用以下方法将其连接到标签夹:
nb.AddPage(tab1, "Tab 1")
nb.AddPage(tab2, "Tab 2")
...
完整代码:
import wx
# Define the tab content as classes:
class TabOne(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
t = wx.StaticText(self, -1, "This is the first tab", (20,20))
class TabTwo(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
t = wx.StaticText(self, -1, "This is the second tab", (20,20))
class TabThree(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
t = wx.StaticText(self, -1, "This is the third tab", (20,20))
class TabFour(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
t = wx.StaticText(self, -1, "This is the last tab", (20,20))
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="wxPython tabs example @pythonspot.com")
# Create a panel and notebook (tabs holder)
p = wx.Panel(self)
nb = wx.Notebook(p)
# Create the tab windows
tab1 = TabOne(nb)
tab2 = TabTwo(nb)
tab3 = TabThree(nb)
tab4 = TabFour(nb)
# Add the windows to tabs and name them.
nb.AddPage(tab1, "Tab 1")
nb.AddPage(tab2, "Tab 2")
nb.AddPage(tab3, "Tab 3")
nb.AddPage(tab4, "Tab 4")
# Set noteboook in a sizer to create the layout
sizer = wx.BoxSizer()
sizer.Add(nb, 1, wx.EXPAND)
p.SetSizer(sizer)
if __name__ == "__main__":
app = wx.App()
MainFrame().Show()
app.MainLoop()
输出:
wx 选项卡