Python权威指南的10个项目(6~10)

发布时间:2020-08-01 17:54:47 作者:原生zzy
来源:网络 阅读:569

6. 项目6:使用CGI进行远程编辑

  这个项目主要用的是的CGI进行远程编辑——在另一台机器上通过Web来编辑 文档。你在一台机器上存储了一个文档,希望能够在另一台机器上通过Web来编辑它。这让多个用 户能够协作编辑一个文档,且无需使用FTP或类似的文件传输技术,也无需操心同步多个副本的 问题。要编辑文件,只要有Web浏览器就行。

(1) 问题描述

#脚本:
#C:\Users\Administrator\AppData\Local\Programs\Python\Python36\python.exe
import cgi
form = cgi.FieldStorage()
text = form.getvalue('text', open('simple_edit.dat').read())
f = open('simple_edit.dat', 'w')
f.write(text)
f.close()
print("Content-type: text/html\n\n")
print("""
<html>
 <head>
 <title>A Simple Editor</title>
 </head>
 <body>
 <form action='simple_edit.py' method='POST'>
 <textarea rows='10' cols='20' name='text'>{}</textarea><br />
 <input type='submit' />
 </form>
 </body>
</html>
""".format(text))

效果:
Python权威指南的10个项目(6~10)
当在输入框中编辑然后提交后,内容会更新到simple_edit.dat中。

###(4) 再次实现
   至此,第一个原型已编写好,它还缺什么呢?应让用户能够编辑多个文件,并使用密码保护 这些文件。相比于第一个原型,再次实现的主要不同在于,你将把它分成两个CGI脚本,分别对应于系 统支持的两种操作。新的原型包含如下文件:

#C:\Users\Administrator\AppData\Local\Programs\Python\Python36\python.exe
print('Content-type: text/html\n\n')
import cgi, sys

form = cgi.FieldStorage()
print('''
<html>
<head>
    <title>File Editor</title>
</head>
<body>
<form action='edit.py' method='POST'>
    <b>File name:</b><br/>
    <input type='text' name='filename'/>
    <input type='submit' value='Open'/>
</form>
</body>
</html>
''')

   文本框名为filename,这确保其内容将通过CGI参数filename提供给脚本edit.cgi,如果在文本框中输入文件名,再 单击Open按钮,将运行脚本edit.cgi。
② 编写编辑器脚本
  脚本edit.cgi显示的页面应包含一个文本区域和一个文本框,其中前者包含当前编辑的文件的 内容,而后者用于输入密码。这个脚本需要的唯一输入是文件名,它是从index.html中的表单中获得的。然而,可在不提交index.html中表单的情况下直接运行脚本edit.py。在这种情况下, cgi.FieldStorage的字段将是未设置的。因此,你需要检查是否获得了文件名;如果获得了,就 打开指定目录中的这个文件。我们将这个目录命名为data(当然,你必须创建这个目录)。
③ 编写保存脚本
  这个简单系统的最后一部分是执行保存的脚本。它接收文件名、密码和一些文本,并检查密 码是否正确;如果正确,就将这些文本存储到指定的文件中。我们将使用模块sha来处理密码。

(5) 结果展示

Python权威指南的10个项目(6~10)

7. 项目7:自建公告板

  本项目实现的是基于Web的论坛,虽然其功能与复杂的社交媒体平台相距甚远,但提供了评论系统的基本功能。

(1) 问题描述

  在这个项目中,你将创建一个通过Web发布和回复消息的简单系统,它可作为论坛使用。这 个系统非常简单,但提供了基本的功能,并能够处理大量的帖子。
  本章介绍的技术不仅可用于开发独立论坛,还可用于实现更通用的协作系统、问题跟踪系统、 带评论功能的博客等。通过将支持在消息下方以缩放的方式显示回复CGI(或类似的技术)和可靠的数据库(这里是SQL数据库)结合 起来使用,可实现非常强大的功能,而且用途非常广泛。
最终这个项目要实现的功能:

#连接数据库脚本:
import pymysql

def create_table(cursor,table_name,create_sql):
    # 使用 execute() 方法执行 SQL,如果表存在则删除
    drop_table = 'drop table if EXISTS '+table_name
    cursor.execute(drop_table)
    # 建表
    cursor.execute(sql)

def insert(cursor,table_name):
    reply_to = input('Reply to: ')
    subject = input('Subject: ')
    sender = input('Sender: ')
    text = input('Text: ')
    sql='insert into {}(reply_to, sender, subject, text) values({},"{}","{}","{}")'\
        .format(table_name,reply_to, sender, subject, text)
    cursor.execute(sql)

if __name__=='__main__':
    server_host="localhost"
    user="xxxx"
    passwd= "xxxx"
    db_name="test"
    # 打开数据库连接
    db = pymysql.connect(server_host, user,passwd,db_name)
    # 使用 cursor() 方法创建一个游标对象 cursor
    cursor = db.cursor()
    #建表
    sql = '''
    CREATE TABLE messages (
     id INT NOT NULL AUTO_INCREMENT,
     subject VARCHAR(100) NOT NULL,
     sender VARCHAR(15) NOT NULL,
     reply_to INT,
     text MEDIUMTEXT NOT NULL, PRIMARY KEY(id)
    )
    '''
    create_table(cursor,"messages",sql)
    #插入数据
    insert(cursor,db_name+".messages")
    db.commit()
    # 关闭连接
    cursor.close()
#cgi脚本:
'''
 公告板主页
'''

print('Content-type: text/html\n')
import cgitb;

cgitb.enable()

import pymysql

server_host = "localhost"
user = "root"
passwd = "123456"
db_name = "test"
# 打开数据库连接
db = pymysql.connect(server_host, user, passwd, db_name)
curs = db.cursor()

print("""
<html>
 <head>
 <title>The FooBar Bulletin Board</title>
 </head>
 <body>
 <h2>The FooBar Bulletin Board</h2> 
""")
toplevel = []
children = {}
curs.execute('SELECT * FROM test.messages')
rows = curs.fetchall()
for row in rows:
    parent_id = row[3]
    if parent_id is None:
        toplevel.append(row)
    else:
        children.setdefault(parent_id, []).append(row)

def format(row):
    print(row[1]+'</br>')
    try:
        kids = children[row[0]]
    except KeyError:
        pass
    else:
        print('<blockquote>')
        for kid in kids:
            format(kid)
        print('</blockquote>')

print('<p>')
for row in toplevel:
    format(row)
print("""
 </p>
 </body>
 </html>
 """)

(4) 最终版

  初次实现的功能很有限,用户甚至不能发布消息。这里我们将内容丰富一些:

(2) 工作准备

#Server:
'''
对下面案例的解释:
方法register_instance注册一个实现了其“远程方法”的实例,也
可使用方法register_function注册各个函数。为运行服务器做好准备(让它能够响应来自外部的
请求)后,调用其方法serve_forever ,方法serve_forever解释器看起来就像“挂起”了一样,但实际上它是在等待RPC请求。
'''
from xmlrpc.server import SimpleXMLRPCServer
s=SimpleXMLRPCServer(("",16888)) #localhost和端口4242
def twice(x):
    return x*2
s.register_function(twice)  # 给服务器添加功能,也就是客户端调用的函数
s.serve_forever() # 启动服务器
#Server:
'''
对下面案例的解释:
方法register_instance注册一个实现了其“远程方法”的实例,也
可使用方法register_function注册各个函数。为运行服务器做好准备(让它能够响应来自外部的
请求)后,调用其方法serve_forever ,方法serve_forever解释器看起来就像“挂起”了一样,但实际上它是在等待RPC请求。
'''
from xmlrpc.server import SimpleXMLRPCServer
s=SimpleXMLRPCServer(("",16888)) #localhost和端口4242
def twice(x):
    return x*2
s.register_function(twice)  # 给服务器添加功能,也就是客户端调用的函数
s.serve_forever() # 启动服务器

先运行server在运行client,我们发现:
在server中出现:
Python权威指南的10个项目(6~10)
而client成功调用了sever的方法,并输出了结果:4。
是不是挺简单的,好像URL请求一样,接下来我们就要根据上面的需求实现相应的功能了:
① 定义node
  回顾需求,我们关心的主要有两点:Node 必须存储哪些信息(属性);Node必须能够执行哪些操作(方法)。
所有node需要有以下属性:
  - 目录名:让Node知道到哪里去查找文件或将文件存储到哪里。
  -密码:供其他节点用来将自己标识为可信任方。
  - 一组已知的对等体(URL)。
  - URL:可能加入到查询历史记录中或提供给其他节点

Node能执行什么操作呢,必须定义一些方法:
  - 用于查询的方法(query)
  - 获取和存储文件的方法(fetch)
  - 向其他节点介绍自己的方法(hello)

② fetch方法解读
  这个方法必须接受参数query和 secret,其中secret是必不可少的, 可避免节点被其他节点随便操纵。调用fetch将导致节 点下载一个文件。如果提供的密码不同于(启动时指定的)self.secret,fetch将直接返回FAIL; 否则它将调 用query来获取指定的文件。调用query时,你希望能够知道查询是否 成功,并在成功时返回指定文件的内容。因此,我们将query的返回值定义为元组(code, data), 其中code的可能取值为OK和FAIL,而data是一个字符串。如果code为OK,这个字符串将包含找到 的文件的内容;否则为一个随意的值,如空字符串。如果查询成功,并且返回OK,则开始创建一个文件并开始向其中写入内容。
③ query方法解读
query的结构:query→self._handle→_broadcast
  首先调用_handle方法,它负责查询的内容处理(检查节点是否包含指定的文件,获取数据 等),它像query一样返回一个编码和一些数据。如果code为OK,则直接返回,如果为FAIL,就需要其他节点的帮助因此它需要将self.url 添加到history中,然后通过history向方法_broadcast向所有已知的对等体广播查询,它迭代self.known的副本,如果当前对等体包含在history中, 就使用continue语句跳到下一个对等体,否则创建一个ServerProxy对象,并对其调用方法query。 如果方法query成功,就将其返回值作为_broadcast的返回值。

由于代码比较长这里就不给出了,可以在小编的git中下载。
最后我们演示一定这个初级版的程序如何运行:

mypeer:python xxx.py  http://localhost:16888 file1 123456 
otherpeer:python xxx.py  http://localhost:16889 file2 123456

#创建mypeer

Python权威指南的10个项目(6~10)
它访问file2下的文件:
Python权威指南的10个项目(6~10)
然后创建otherpeer:
Python权威指南的10个项目(6~10)
它访问file1下的文件:
Python权威指南的10个项目(6~10)
把mypeer介绍给otherpeer:
Python权威指南的10个项目(6~10)
然后在访问file1下的文件:
Python权威指南的10个项目(6~10)
通过otherpeer拉去file1下的文件:
Python权威指南的10个项目(6~10)
发现file2下有test1.txt:
Python权威指南的10个项目(6~10)

  有朋友想问,这个有啥用啊,我们不妨拓展一下思维,如果这里是一个集群,我们用client去访问server中的文件,但是文件分布在server集群的某个节点上,想想我们可不可通过这种方法,把文件传递到访问的节点上,然后从访问节点中拿取,我的天一不小心了解分布式的原理,低调低调。

(4) 最终实现

最终版我们需要在初次实现中修改一些内容:

③ 验证文件名
  检查指定的文件是否包含在指定的目录中。我们这里采用较为简单的方法实现:
根据目录名和文件名创建绝对路径(例如,这将把'/foo/bar/../ baz'转换为'/foo/baz'),将目录名与空文件名合并以确保它以文件分隔符(如'/')结尾,再检 查绝对文件名是否以绝对路径名打头。如果是这样的,就说明指定的文件包含在指定的目录中。

(5) 结果展示

  这里在pychram中运行有诸多bug,使用cmd感觉不是那么好使,或者可以在Linux下运行试试,这里小编也给出了一个Cmd运行的dome,大概是这样的:
Python权威指南的10个项目(6~10)
在Miller2>后面输入,定义的do_xxx的方法中的xxx,它就会执行相应方法中的内容。
最后小编在这里说一下这个项目的运行规则:
运行:python client.py urls.txt directory http://servername.com:16888
Python权威指南的10个项目(6~10)
执行错误操作:
Python权威指南的10个项目(6~10)
首先查询所有的能关联的所有的urls列表,没有的返回Couldn't find the file 123。
输入exit 或者EOF会退出程序:
Python权威指南的10个项目(6~10)

9. 项目9:使用GUI共享文件

这个项目较小,你将看到给既 有Python程序添加GUI非常容易。

(1) 问题描述

  开发的文件共享系统:添加GUI客户端,让它使用起来更 容易。这意味着可能有更多的人选择使用它,他实现的需求是:

10. 项目10:自制街机游戏

  到了最后一个项目了,这也是Python权威指南的最后一课了,经过一个多月的学习对Python也有了大致的了解,希望以后可以运用到工作中,至少目前看代码时完全没有问题。
  最后一个项目,应该说是所有项目中代码量最多的,而且也比较有趣,这个项目将学习如何使用Pygame,这个扩展让你能够使用Python编写功能齐备的全屏街机游戏。

(1) 问题描述

  这个游戏中,我们将让玩家控制一支香蕉。这支香蕉要躲开从天而 降的16吨铅锤,尽力在防御战中活下来。这个项目的目标是围绕着游戏设计展开的。这款游戏必须像设计的那样:香蕉能够移动,16 吨的铅锤从天而降。另外,与往常一样,代码必须是模块化的,且易于扩展。一个重要的需求是, 设计应包含一些游戏状态(如游戏简介、关卡和“游戏结束”状态),同时可轻松地添加新状态。

(2) 工作准备

  这个项目需要的工具只有一个,那就是pygame。模块pygame自动导入其他所有的Pygame模块,因此只要在程序开头包含语句import pygame, 就能使用其他模块,如pygame.display和pygame.font。
  模块pygame包含函数Surface,它返回一个新的Surface对象。Surface对象其实就是一个指定 尺寸的空图像,可用来绘画和传送。传送(调用Surface对象的方法blit)意味着在Surface之间传输内容。
  函数init是Pygame游戏的核心,必须在游戏进入主事件循环前调用。这个函数自动初始化其他所有模块(如font和image)。

下载:pip install pygame

如果要捕获Pygame特有的错误,就需要使用error类。
接下来我们再来了解几个pygame重要的函数:

(3) 初次实现

在初次实现的时候,我们只实现其中一些简单的功能:

# C:\Users\Administrator\AppData\Local\Programs\Python\Python36\python.exe
# -*- coding: utf-8 -*-

'''
    简单的“铅锤从天而降”动画
'''

import sys,pygame
from random import randrange
from pygame.locals import *

class Weight(pygame.sprite.Sprite):
    def __init__(self,speed):
        pygame.sprite.Sprite.__init__(self)
        self.speed=speed
        #绘制Sprite对象时要用到的图像和矩形:
        self.image=weight_image
        self.rect=self.image.get_rect()
        self.reset()

    def reset(self):
        """
       将铅锤移到屏幕顶端的一个随机位置
        """
        self.rect.top=-self.rect.height
        self.rect.centerx=randrange(screen_size[0])

    def update(self):
        """
       更新下一帧中的铅锤
        """
        if self.rect.top> screen_size[1]:
            self.reset()
        self.rect.top += self.speed
#初始化
pygame.init()
screen_size=1366,768
pygame.display.set_mode(screen_size,FULLSCREEN)
pygame.mouse.set_visible(0)

# 加载铅锤图像
image_path="images/jack.jpg"
weight_image=pygame.image.load(image_path)
weight_image=weight_image.convert() # 以便与显示匹配

# 你可能想设置不同的速度
#speed=5

# 创建一个Sprite对象编组,并在其中添加一个Weight实例
sprites = pygame.sprite.RenderUpdates()
#同时添加三个铅块
sprites.add(Weight(speed=2))
sprites.add(Weight(speed=3))
sprites.add(Weight(speed=5))

# 获取并填充屏幕表面
screen=pygame.display.get_surface()
bg=(255, 255, 255) #白色
#以白色填充屏幕表面
screen.fill(bg)
#显示所做的修改
pygame.display.flip()

clock=pygame.time.Clock() # 设置时钟,限制移动速度

# 用于清除Sprite对象:
def clear_back(surf,rect):
    surf.fill(bg, rect)

while True:
    clock.tick(60)  # 然后在while循环中设置多长时间运行一次,每秒执行60次
    # 检查退出事件:
    for event in pygame.event.get():
        if event.type==QUIT:
            sys.exit()
        if event.type== KEYDOWN and event.key == K_ESCAPE:
            sys.exit()
    # 清除以前的位置:
    sprites.clear(screen,clear_back)
    # 更新所有的Sprite对象:
    sprites.update() #方法update调用Weight实例的方法update
    # 绘制所有的Sprite对象:
    updates=sprites.draw(screen) #调用sprites.draw并将屏幕表面作为参数,以便在当前位置绘制铅锤
    # 更新必要的显示部分:
    pygame.display.update(updates)

(4) 再次实现

最终我们将实现这样的一个游戏:

这里我们将实现这样几个模块:
config.py:可根据偏好随意修改配置变量,如果游戏的节奏太快或太慢,可尝试修改与速度相关的变量
objects.py:这个模块包含游戏Squish使用的游戏对象
squish.py:这个模块包含游戏Squish的主游戏逻辑

(5) 最终展示

开始界面:
Python权威指南的10个项目(6~10)
游戏界面:
Python权威指南的10个项目(6~10)
闯关界面:
Python权威指南的10个项目(6~10)
结束界面:
Python权威指南的10个项目(6~10)

到此所有的项目都已结束!!!
所有的代码 小编都上传到gitlab上:

https://gitlab.com/ZZY478086819/actualcombatproject

推荐阅读:
  1. DEDECMS站点内容自动更新到新浪微博的方法
  2. 怎么在Win7中通过修改注册表加快程序反应

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

python小项目 权威

上一篇:[Cocos2D-X] CocoStudio Test 解密

下一篇:linux环境安装python3的环境(包含setuptoo

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》