标签 python 下的文章

在我们这个包含了 7 个 PyPI 库的系列文章中学习解决常见的 Python 问题的方法。

Python 是当今使用最多的流行编程语言之一,因为:它是开源的,它有广泛的用途(例如 Web 编程、业务应用、游戏、科学编程等等),它有一个充满活力和专注的社区支持它。这个社区可以让我们在 Python Package Index(PyPI)中有如此庞大、多样化的软件包,用以扩展和改进 Python 并解决不可避免的问题。

在本系列中,我们将介绍七个可以帮助你解决常见 Python 问题的 PyPI 库。首先是 Cython,一个简化 Python 编写 C 扩展的语言。

Cython

使用 Python 很有趣,但有时,用它编写的程序可能很慢。所有的运行时动态调度会带来很大的代价:有时它比用 C 或 Rust 等系统语言编写的等效代码慢 10 倍。

将代码迁移到一种全新的语言可能会在成本和可靠性方面付出巨大代价:所有的手工重写工作都将不可避免地引入错误。我们可以两者兼得么?

为了练习一下优化,我们需要一些慢代码。有什么比斐波那契数列的意外指数实现更慢?

def fib(n):
  if n < 2:
    return 1
  return fib(n-1) + fib(n-2)

由于对 fib 的调用会导致两次再次调用,因此这种效率极低的算法需要很长时间才能执行。例如,在我的新笔记本电脑上,fib(36) 需要大约 4.5 秒。这个 4.5 秒会成为我们探索 Python 的 Cython 扩展能提供的帮助的基准。

使用 Cython 的正确方法是将其集成到 setup.py 中。然而,使用 pyximport 可以快速地进行尝试。让我们将 fib 代码放在 fib.pyx 中并使用 Cython 运行它。

>>> import pyximport; pyximport.install()
>>> import fib
>>> fib.fib(36)

只使用 Cython 而不修改代码,这个算法在我笔记本上花费的时间减少到大约 2.5 秒。几乎无需任何努力,这几乎减少了 50% 的运行时间。当然,得到了一个不错的成果。

加把劲,我们可以让它变得更快。

cpdef int fib(int n):
  if n < 2:
    return 1
  return fib(n - 1) + fib(n - 2)

我们将 fib 中的代码变成用 cpdef 定义的函数,并添加了两个类型注释:它接受一个整数并返回一个整数。

这个变得快了,大约只用了 0.05 秒。它是如此之快,以至于我可能开始怀疑我的测量方法包含噪声:之前,这种噪声在信号中丢失了。

当下次你的 Python 代码花费太多 CPU 时间时,也许会导致风扇狂转,为何不看看 Cython 是否可以解决问题呢?

在本系列的下一篇文章中,我们将看一下 Black,一个自动纠正代码格式错误的项目。

(题图:Subgrafik San


via: https://opensource.com/article/19/5/python-cython

作者:Moshe Zadka 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这是用 Python 从头开始构建游戏的系列文章的第三部分。

这个系列的第一篇文章 中,我解释了如何使用 Python 创建一个简单的基于文本的骰子游戏。在第二部分中,我向你们展示了如何从头开始构建游戏,即从 创建游戏的环境 开始。但是每个游戏都需要一名玩家,并且每个玩家都需要一个可操控的角色,这也就是我们接下来要在这个系列的第三部分中需要做的。

在 Pygame 中,玩家操控的图标或者化身被称作 妖精 sprite 。如果你现在还没有任何可用于玩家妖精的图像,你可以使用 KritaInkscape 来自己创建一些图像。如果你对自己的艺术细胞缺乏自信,你也可以在 OpenClipArt.orgOpenGameArt.org 搜索一些现成的图像。如果你还未按照上一篇文章所说的单独创建一个 images 文件夹,那么你需要在你的 Python 项目目录中创建它。将你想要在游戏中使用的图片都放 images 文件夹中。

为了使你的游戏真正的刺激,你应该为你的英雄使用一张动态的妖精图片。这意味着你需要绘制更多的素材,并且它们要大不相同。最常见的动画就是走路循环,通过一系列的图像让你的妖精看起来像是在走路。走路循环最快捷粗糙的版本需要四张图像。

注意:这篇文章中的代码示例同时兼容静止的和动态的玩家妖精。

将你的玩家妖精命名为 hero.png。如果你正在创建一个动态的妖精,则需要在名字后面加上一个数字,从 hero1.png 开始。

创建一个 Python 类

在 Python 中,当你在创建一个你想要显示在屏幕上的对象时,你需要创建一个类。

在你的 Python 脚本靠近顶端的位置,加入如下代码来创建一个玩家。在以下的代码示例中,前三行已经在你正在处理的 Python 脚本中:

import pygame
import sys
import os # 以下是新代码

class Player(pygame.sprite.Sprite):
    '''
    生成一个玩家
    '''
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.images = []
    img = pygame.image.load(os.path.join('images','hero.png')).convert()
    self.images.append(img)
    self.image = self.images[0]
    self.rect  = self.image.get_rect()

如果你的可操控角色拥有一个走路循环,在 images 文件夹中将对应图片保存为 hero1.pnghero4.png 的独立文件。

使用一个循环来告诉 Python 遍历每个文件。

'''
对象
'''

class Player(pygame.sprite.Sprite):
    '''
    生成一个玩家
    '''
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.images = []
        for i in range(1,5):
            img = pygame.image.load(os.path.join('images','hero' + str(i) + '.png')).convert()
            self.images.append(img)
            self.image = self.images[0]
            self.rect  = self.image.get_rect()

将玩家带入游戏世界

现在已经创建好了一个 Player 类,你需要使用它在你的游戏世界中生成一个玩家妖精。如果你不调用 Player 类,那它永远不会起作用,(游戏世界中)也就不会有玩家。你可以通过立马运行你的游戏来验证一下。游戏会像上一篇文章末尾看到的那样运行,并得到明确的结果:一个空荡荡的游戏世界。

为了将一个玩家妖精带到你的游戏世界,你必须通过调用 Player 类来生成一个妖精,并将它加入到 Pygame 的妖精组中。在如下的代码示例中,前三行是已经存在的代码,你需要在其后添加代码:

world       = pygame.display.set_mode([worldx,worldy])
backdrop    = pygame.image.load(os.path.join('images','stage.png')).convert()
backdropbox = screen.get_rect()

# 以下是新代码

player = Player()   # 生成玩家
player.rect.x = 0   # 移动 x 坐标
player.rect.y = 0   # 移动 y 坐标
player_list = pygame.sprite.Group()
player_list.add(player)

尝试启动你的游戏来看看发生了什么。高能预警:它不会像你预期的那样工作,当你启动你的项目,玩家妖精没有出现。事实上它生成了,只不过只出现了一毫秒。你要如何修复一个只出现了一毫秒的东西呢?你可能回想起上一篇文章中,你需要在主循环中添加一些东西。为了使玩家的存在时间超过一毫秒,你需要告诉 Python 在每次循环中都绘制一次。

将你的循环底部的语句更改如下:

    world.blit(backdrop, backdropbox)
    player_list.draw(screen) # 绘制玩家
    pygame.display.flip()
    clock.tick(fps)

现在启动你的游戏,你的玩家出现了!

设置 alpha 通道

根据你如何创建你的玩家妖精,在它周围可能会有一个色块。你所看到的是 alpha 通道应该占据的空间。它本来是不可见的“颜色”,但 Python 现在还不知道要使它不可见。那么你所看到的,是围绕在妖精周围的边界区(或现代游戏术语中的“ 命中区 hit box ”)内的空间。

你可以通过设置一个 alpha 通道和 RGB 值来告诉 Python 使哪种颜色不可见。如果你不知道你使用 alpha 通道的图像的 RGB 值,你可以使用 Krita 或 Inkscape 打开它,并使用一种独特的颜色,比如 #00ff00(差不多是“绿屏绿”)来填充图像周围的空白区域。记下颜色对应的十六进制值(此处为 #00ff00,绿屏绿)并将其作为 alpha 通道用于你的 Python 脚本。

使用 alpha 通道需要在你的妖精生成相关代码中添加如下两行。类似第一行的代码已经存在于你的脚本中,你只需要添加另外两行:

            img = pygame.image.load(os.path.join('images','hero' + str(i) + '.png')).convert()
            img.convert_alpha()     # 优化 alpha
            img.set_colorkey(ALPHA) # 设置 alpha

除非你告诉它,否则 Python 不知道将哪种颜色作为 alpha 通道。在你代码的设置相关区域,添加一些颜色定义。将如下的变量定义添加于你的设置相关区域的任意位置:

ALPHA = (0, 255, 0)

在以上示例代码中,0,255,0 被我们使用,它在 RGB 中所代表的值与 #00ff00 在十六进制中所代表的值相同。你可以通过一个优秀的图像应用程序,如 GIMP、Krita 或 Inkscape,来获取所有这些颜色值。或者,你可以使用一个优秀的系统级颜色选择器,如 KColorChooser,来检测颜色。

如果你的图像应用程序将你的妖精背景渲染成了其他的值,你可以按需调整 ALPHA 变量的值。不论你将 alpha 设为多少,最后它都将“不可见”。RGB 颜色值是非常严格的,因此如果你需要将 alpha 设为 000,但你又想将 000 用于你图像中的黑线,你只需要将图像中线的颜色设为 111。这样一来,(图像中的黑线)就足够接近黑色,但除了电脑以外没有人能看出区别。

运行你的游戏查看结果。

这个系列的第四篇文章 中,我会向你们展示如何使你的妖精动起来。多么的激动人心啊!


via: https://opensource.com/article/17/12/game-python-add-a-player

作者:Seth Kenlon 选题:lujun9972 译者:cycoe 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

介绍

Python 与 PHP 都是广泛使用的语言,各有所长,让人期待两者结合可以实现更丰富的效果。

在 PHP 中调用 Python 实现某些处理,这种需求虽然比较小众,还是实用的。目前网上可以查到很多资料仍在探讨 exec()(也包括 system()shell_exec()passthru() 等)执行外部的 Python 文件,但这只是一种通用的方式,调用成本比较高,在每次调用时,需要装载整个 Python 解释环境。

有此类需求的开发者非常适合看一下 PPython,这是一种从根本上将 PHP 与 Python 有效结合的技术。

PPython 最初见于 https://code.google.com/p/ppython,该作者将 lajp(一种 PHP 结合 Java 的技术)移植到了 Python 上。

该项目最初建立于 2012 年,而且似乎已经停止维护多年,不过目前来看其思路及效果还是值得肯定的,因此将此项目从停止运营的 Google Code 上迁移到了 GitHub,并遵循原 Apache 许可证重新发布和维护。

日前笔者对此作了一番尝试,对 PPython 的方便易用有所体会。

原理与架构

PHP 与 Python 通讯有两种不同的套接字机制:TCP 套接字和 UNIX 套接字。UNIX 套接字是 Unix/Linux 本地套接字,相对于 TCP 套接字,具有以下特点:

  • 只能在同一台主机中通讯(IPC),不能跨主机;
  • 传输速度大于 TCP 套接字;
  • 服务端只向本机提供服务(没有对外侦听端口),相对安全,易于管理。

PHP 和 Python 各有其语言内部定义的数据类型,通常 PHP 进程与 Python 进程进行数据交互时,需要进行转码处理。此类转换如由应用自行实现,从开发效率到运行性能都会增加不少额外负担。

PPython 对 PHP 和 Python 间的通讯方式的处理支持 TCP 套接字和 UNIX 套接字两种机制,兼顾通讯效率和分布式,转码由服务统一处理,Python 为 PHP 的数据类型提供格式兼容,使 PHP 端开发无须为底层通讯担心。

Python 因其语言 GIL 特性,同一进程内多线程效率不高。PPython 可根据项目需要部署服务,多进程运行 Python,提高应用综合性能。

使用方法

PPython 的代码可从上述项目仓库中下载。

下载得到的文件中,以下三个是 PPython 的核心代码,作用如下:

  • php_python.py,Python 进程主文件,完成 Python 端监听请求并运行返回
  • process.py,Python 端核心类,实现 Python 内部进程调用及 PHP 与 Python 数据结构转化等关键处理
  • php_python.php,PPython 客户端,PHP 端引用此文件,可直接使用 PPython 函数实现调用。

将以上文件放置到任意目录。先修改准备运行 PPython 的端口,监听端口不限,只要 php_python.pyphp_python.php 两端修改一致。笔者统一改为 10240。

在当前目录下运行 php_python.py,只要 Python 环境正常,便将运行起一个 PPython 的服务。

-------------------------------------------
- PPython Service
- Time: 2019-05-13 22:24:09
-------------------------------------------
Listen port: 10240
charset: utf-8
Server startup...

PHP 端引入 php_python.php,就可以用 ppython 函数与之前启动的 PPython 服务通讯,传入请求由 PPython 服务调用 Python 处理后返回结果,如 $res = ppython('test::go') 是调用test.py 中的 go 函数,也可加上更多参数,第二个参数起将为被调的函数传递更多参数。

php_python.py 是 PPython 启动后直接运行的全局代码,有全局配置或进程启动后的通用处理都写在这里,如原生代码中建立了数据库连接等,项目中应视情况作优化。

但 Python 令人感兴趣的主要方面不只是像 PHP 那样描述业务功能,它可以在人工智能等领域所需要的计算型任务提供对更复杂的数据结构的处理,因此二者的结合可以给 PHP 带来更多应用场景。

改进

此外,原生的 php_python.py 还有些不足。笔者用 ppython 调用自定义代码中遇到了三个问题,并相应做了解决:

  1. 不支持 complex(复数类),复数是数学上的一种数据类型,主要包括 real(实部)和 imag(虚部)数据,虽然日常生活中遇到较少,但 AI 和各种专业研究领域或并不罕见。Python 里有 complex 类,对复数可以直接进行各种计算,但 PPython 序列化和反序列化对 complex 没有处理。为了能让 complex 包括的数据能正常返回,只要在 process.pyz_encode() 方法中加上符合 PHP 要求的序列化处理,代码如下:
elif isinstance(p, numpy.complex128):
    t1 = str(p.real)
    t2 = str(p.imag)
    return 'O:7:"complex":2:{s:4:"real";d:%s;s:4:"imag";d:%s;}' % (t1,t2)
  1. 不支持 ndarray(多维数组)。相比 complexndarray 要普通得多,相信凡使用到 Python 的各种计算功能,ndarray 是无法回避的,甚至 ndarray 在一定程度上成就了 Python。但原 php_python.py 不能识别 ndarray。不过解决起来并不难,在 process.py 里找到z_encode() 方法,加上下面这段,可以直接将 ndarray 转化为符合 PHP 要求的数组(数字索引)。
    elif isinstance(p, numpy.ndarray):
        s = ''
        i = 0
        for d in p:
            s += 'i:%d;%s' % (i,z_encode(d))
            i += 1
        return "a:%d:{%s}" % (len(p),s)
  1. 原代码不太稳健,如数据为 ndarray 类型,if p == None:报错ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all(),因为p == None的结果也是ndarray,不返回false ,将判断方法改为if p is None:可避免出错。

相应地 PHP 端也要注意一下序列化和反序列化的处理。

处理回复中类似 complex 这样的对象数据时,如系统中没有定义相应的类,PHP 是可以反序列化的,但将显示为 “incomplete object”,vardump 看得到 realimag 数据,但不能直接操作,自行定义 complex 类后,则按指定的类进行解析,与 PHP 内的一般对象无异,可以轻松进行所有操作。

至此,PHP 与 Python 的功能调讯已无问题。

补充:注册为服务

命令行下启动 php_python.py 主要是方便调试,可以看到观察反馈信息等,生产环境中手工启动 PPython 毕竟不太方便。可以将 PPython 配置成服务,修改端口也可以为不同的应用配置不同的 PPython 端。

Linux 下将一个进程注册为服务很简单,只要建立 /usr/lib/systemd/system/ppython.service,内容如下:

[Unit]
Description=PHP-Python Service
After=network.target remote-fs.target nss-lookup.target
 
[Service]
ExecStart={PPYTHON_PATH}/php_python.py

[Install]
WantedBy=multi-user.target

其中 {PPYTHON_PATH} 要改成实际路径。

总结

有了 PPython,可以摒弃 exec() 这种 shell 调用,使开发回归到逻辑本身。

个人认为该方案值得所有对 PHP 和 Python 都感兴趣的开发人员了解,也欢迎大家参与和贡献这个项目

这系列的第一篇通过创建一个简单的骰子游戏来探究 Python。现在是来从零制作你自己的游戏的时间。

在我的这系列的第一篇文章 中, 我已经讲解如何使用 Python 创建一个简单的、基于文本的骰子游戏。这次,我将展示如何使用 Python 模块 Pygame 来创建一个图形化游戏。它将需要几篇文章才能来得到一个确实做成一些东西的游戏,但是到这系列的结尾,你将更好地理解如何查找和学习新的 Python 模块和如何从其基础上构建一个应用程序。

在开始前,你必须安装 Pygame

安装新的 Python 模块

有几种方法来安装 Python 模块,但是最通用的两个是:

  • 从你的发行版的软件存储库
  • 使用 Python 的软件包管理器 pip

两个方法都工作的很好,并且每一个都有它自己的一套优势。如果你是在 Linux 或 BSD 上开发,可以利用你的发行版的软件存储库来自动和及时地更新。

然而,使用 Python 的内置软件包管理器可以给予你控制更新模块时间的能力。而且,它不是特定于操作系统的,这意味着,即使当你不是在你常用的开发机器上时,你也可以使用它。pip 的其它的优势是允许本地安装模块,如果你没有正在使用的计算机的管理权限,这是有用的。

使用 pip

如果 Python 和 Python3 都安装在你的系统上,你想使用的命令很可能是 pip3,它用来区分 Python 2.x 的 pip 的命令。如果你不确定,先尝试 pip3

pip 命令有些像大多数 Linux 软件包管理器一样工作。你可以使用 search 搜索 Python 模块,然后使用 install 安装它们。如果你没有你正在使用的计算机的管理权限来安装软件,你可以使用 --user 选项来仅仅安装模块到你的家目录。

$ pip3 search pygame
[...]
Pygame (1.9.3)                 - Python Game Development
sge-pygame (1.5)               - A 2-D game engine for Python
pygame_camera (0.1.1)          - A Camera lib for PyGame
pygame_cffi (0.2.1)            - A cffi-based SDL wrapper that copies the pygame API.
[...]
$ pip3 install Pygame --user

Pygame 是一个 Python 模块,这意味着它仅仅是一套可以使用在你的 Python 程序中的库。换句话说,它不是一个像 IDLENinja-IDE 一样可以让你启动的程序。

Pygame 新手入门

一个电子游戏需要一个背景设定:故事发生的地点。在 Python 中,有两种不同的方法来创建你的故事背景:

  • 设置一种背景颜色
  • 设置一张背景图片

你的背景仅是一张图片或一种颜色。你的电子游戏人物不能与在背景中的东西相互作用,因此,不要在后面放置一些太重要的东西。它仅仅是设置装饰。

设置你的 Pygame 脚本

要开始一个新的 Pygame 工程,先在计算机上创建一个文件夹。游戏的全部文件被放在这个目录中。在你的工程文件夹内部保持所需要的所有的文件来运行游戏是极其重要的。

一个 Python 脚本以文件类型、你的姓名,和你想使用的许可证开始。使用一个开放源码许可证,以便你的朋友可以改善你的游戏并与你一起分享他们的更改:

#!/usr/bin/env python3
# by Seth Kenlon

## GPLv3
# This program is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

然后,你告诉 Python 你想使用的模块。一些模块是常见的 Python 库,当然,你想包括一个你刚刚安装的 Pygame 模块。

import pygame  # 加载 pygame 关键字
import sys     # 让 python 使用你的文件系统
import os      # 帮助 python 识别你的操作系统

由于你将用这个脚本文件做很多工作,在文件中分成段落是有帮助的,以便你知道在哪里放代码。你可以使用块注释来做这些,这些注释仅在看你的源文件代码时是可见的。在你的代码中创建三个块。

'''
Objects
'''

# 在这里放置 Python 类和函数

'''
Setup
'''

# 在这里放置一次性的运行代码

'''
Main Loop
'''

# 在这里放置游戏的循环代码指令

接下来,为你的游戏设置窗口大小。注意,不是每一个人都有大计算机屏幕,所以,最好使用一个适合大多数人的计算机的屏幕大小。

这里有一个方法来切换全屏模式,很多现代电子游戏都会这样做,但是,由于你刚刚开始,简单起见仅设置一个大小即可。

'''
Setup
'''
worldx = 960
worldy = 720

在脚本中使用 Pygame 引擎前,你需要一些基本的设置。你必须设置帧频,启动它的内部时钟,然后开始 (init)Pygame 。

fps   = 40  # 帧频
ani   = 4   # 动画循环
clock = pygame.time.Clock()
pygame.init()

现在你可以设置你的背景。

设置背景

在你继续前,打开一个图形应用程序,为你的游戏世界创建一个背景。在你的工程目录中的 images 文件夹内部保存它为 stage.png

这里有一些你可以使用的自由图形应用程序。

  • Krita 是一个专业级绘图素材模拟器,它可以被用于创建漂亮的图片。如果你对创建电子游戏艺术作品非常感兴趣,你甚至可以购买一系列的游戏艺术作品教程
  • Pinta 是一个基本的,易于学习的绘图应用程序。
  • Inkscape 是一个矢量图形应用程序。使用它来绘制形状、线、样条曲线和贝塞尔曲线。

你的图像不必很复杂,你可以以后回去更改它。一旦有了它,在你文件的 Setup 部分添加这些代码:

world    = pygame.display.set_mode([worldx,worldy])
backdrop = pygame.image.load(os.path.join('images','stage.png').convert())
backdropbox = world.get_rect()

如果你仅仅用一种颜色来填充你的游戏的背景,你需要做的就是:

world = pygame.display.set_mode([worldx,worldy])

你也必须定义颜色以使用。在你的 Setup 部分,使用红、绿、蓝 (RGB) 的值来创建一些颜色的定义。

'''
Setup
'''

BLUE  = (25,25,200)
BLACK = (23,23,23 )
WHITE = (254,254,254)

至此,你理论上可以启动你的游戏了。问题是,它可能仅持续了一毫秒。

为证明这一点,保存你的文件为 your-name_game.py(用你真实的名称替换 your-name)。然后启动你的游戏。

如果你正在使用 IDLE,通过选择来自 “Run” 菜单的 “Run Module” 来运行你的游戏。

如果你正在使用 Ninja,在左侧按钮条中单击 “Run file” 按钮。

你也可以直接从一个 Unix 终端或一个 Windows 命令提示符中运行一个 Python 脚本。

$ python3 ./your-name_game.py

如果你正在使用 Windows,使用这命令:

py.exe your-name_game.py

启动它,不过不要期望很多,因为你的游戏现在仅仅持续几毫秒。你可以在下一部分中修复它。

循环

除非另有说明,一个 Python 脚本运行一次并仅一次。近来计算机的运行速度是非常快的,所以你的 Python 脚本运行时间会少于 1 秒钟。

为强制你的游戏来处于足够长的打开和活跃状态来让人看到它(更不要说玩它),使用一个 while 循环。为使你的游戏保存打开,你可以设置一个变量为一些值,然后告诉一个 while 循环只要变量保持未更改则一直保存循环。

这经常被称为一个“主循环”,你可以使用术语 main 作为你的变量。在你的 Setup 部分的任意位置添加代码:

main = True

在主循环期间,使用 Pygame 关键字来检查键盘上的按键是否已经被按下或释放。添加这些代码到你的主循环部分:

'''
Main loop
'''
while main == True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit(); sys.exit()
            main = False

        if event.type == pygame.KEYDOWN:
            if event.key == ord('q'):
                pygame.quit()
                sys.exit()
                main = False

也是在你的循环中,刷新你世界的背景。

如果你使用一个图片作为背景:

world.blit(backdrop, backdropbox)

如果你使用一种颜色作为背景:

world.fill(BLUE)

最后,告诉 Pygame 来重新刷新屏幕上的所有内容,并推进游戏的内部时钟。

    pygame.display.flip()
    clock.tick(fps)

保存你的文件,再次运行它来查看你曾经创建的最无趣的游戏。

退出游戏,在你的键盘上按 q 键。

在这系列的 下一篇文章 中,我将向你演示,如何加强你当前空空如也的游戏世界,所以,继续学习并创建一些将要使用的图形!


via: https://opensource.com/article/17/12/game-framework-python

作者:Seth Kenlon 选题:lujun9972 译者:robsean 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

加密你的数据并使其免受攻击者的攻击。

密码学俱乐部的第一条规则是:永远不要自己发明密码系统。密码学俱乐部的第二条规则是:永远不要自己实现密码系统:在现实世界中,在实现以及设计密码系统阶段都找到过许多漏洞。

Python 中的一个有用的基本加密库就叫做 cryptography。它既是一个“安全”方面的基础库,也是一个“危险”层。“危险”层需要更加小心和相关的知识,并且使用它很容易出现安全漏洞。在这篇介绍性文章中,我们不会涵盖“危险”层中的任何内容!

cryptography 库中最有用的高级安全功能是一种 Fernet 实现。Fernet 是一种遵循最佳实践的加密缓冲区的标准。它不适用于非常大的文件,如千兆字节以上的文件,因为它要求你一次加载要加密或解密的内容到内存缓冲区中。

Fernet 支持 对称 symmetric (即 密钥 secret key )加密方式*:加密和解密使用相同的密钥,因此必须保持安全。

生成密钥很简单:

>>> k = fernet.Fernet.generate_key()
>>> type(k)
<class 'bytes'>

这些字节可以写入有适当权限的文件,最好是在安全的机器上。

有了密钥后,加密也很容易:

>>> frn = fernet.Fernet(k)
>>> encrypted = frn.encrypt(b"x marks the spot")
>>> encrypted[:10]
b'gAAAAABb1'

如果在你的机器上加密,你会看到略微不同的值。不仅因为(我希望)你生成了和我不同的密钥,而且因为 Fernet 将要加密的值与一些随机生成的缓冲区连接起来。这是我之前提到的“最佳实践”之一:它将阻止对手分辨哪些加密值是相同的,这有时是攻击的重要部分。

解密同样简单:

>>> frn = fernet.Fernet(k)
>>> frn.decrypt(encrypted)
b'x marks the spot'

请注意,这仅加密和解密字节串。为了加密和解密文本串,通常需要对它们使用 UTF-8 进行编码和解码。

20 世纪中期密码学最有趣的进展之一是 公钥 public key 加密。它可以在发布加密密钥的同时而让解密密钥保持保密。例如,它可用于保存服务器使用的 API 密钥:服务器是唯一可以访问解密密钥的一方,但是任何人都可以保存公共加密密钥。

虽然 cryptography 没有任何支持公钥加密的安全功能,但 PyNaCl 库有。PyNaCl 封装并提供了一些很好的方法来使用 Daniel J. Bernstein 发明的 NaCl 加密系统。

NaCl 始终同时 加密 encrypt 签名 sign 或者同时 解密 decrypt 验证签名 verify signature 。这是一种防止 基于可伸缩性 malleability-based 的攻击的方法,其中攻击者会修改加密值。

加密是使用公钥完成的,而签名是使用密钥完成的:

>>> from nacl.public import PrivateKey, PublicKey, Box
>>> source = PrivateKey.generate()
>>> with open("target.pubkey", "rb") as fpin:
... target_public_key = PublicKey(fpin.read())
>>> enc_box = Box(source, target_public_key)
>>> result = enc_box.encrypt(b"x marks the spot")
>>> result[:4]
b'\xe2\x1c0\xa4'

解密颠倒了角色:它需要私钥进行解密,需要公钥验证签名:

>>> from nacl.public import PrivateKey, PublicKey, Box
>>> with open("source.pubkey", "rb") as fpin:
... source_public_key = PublicKey(fpin.read())
>>> with open("target.private_key", "rb") as fpin:
... target = PrivateKey(fpin.read())
>>> dec_box = Box(target, source_public_key)
>>> dec_box.decrypt(result)
b'x marks the spot'

最后,PocketProtector 库构建在 PyNaCl 之上,包含完整的密钥管理方案。


via: https://opensource.com/article/19/4/cryptography-python

作者:Moshe Zadka 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Dask 库可以将 Python 计算扩展到多个核心甚至是多台机器。

关于 Python 性能的一个常见抱怨是全局解释器锁(GIL)。由于 GIL,同一时刻只能有一个线程执行 Python 字节码。因此,即使在现代的多核机器上,使用线程也不会加速计算。

但当你需要并行化到多核时,你不需要放弃使用 Python:Dask 库可以将计算扩展到多个内核甚至多个机器。某些设置可以在数千台机器上配置 Dask,每台机器都有多个内核。虽然存在扩展规模的限制,但一般达不到。

虽然 Dask 有许多内置的数组操作,但举一个非内置的例子,我们可以计算偏度

import numpy
import dask
from dask import array as darray

arr = dask.from_array(numpy.array(my_data), chunks=(1000,))
mean = darray.mean()
stddev = darray.std(arr)
unnormalized_moment = darry.mean(arr * arr * arr)
## See formula in wikipedia:
skewness = ((unnormalized_moment - (3 * mean * stddev ** 2) - mean ** 3) /
            stddev ** 3)

请注意,每个操作将根据需要使用尽可能多的内核。这将在所有核心上并行化执行,即使在计算数十亿个元素时也是如此。

当然,并不是我们所有的操作都可由这个库并行化,有时我们需要自己实现并行性。

为此,Dask 有一个“延迟”功能:

import dask

def is_palindrome(s):
    return s == s[::-1]

palindromes = [dask.delayed(is_palindrome)(s) for s in string_list]
total = dask.delayed(sum)(palindromes)
result = total.compute()

这将计算字符串是否是回文并返回回文的数量。

虽然 Dask 是为数据科学家创建的,但它绝不仅限于数据科学。每当我们需要在 Python 中并行化任务时,我们可以使用 Dask —— 无论有没有 GIL。


via: https://opensource.com/article/19/4/parallel-computation-python-dask

作者:Moshe Zadka (Community Moderator) 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出