Heard First Python学习心得 (7-10章)

前六章主要是对python的基础知识有一个大致的了解,后面这几章主要是python在web和android上的应用,会涉及HTML和sqlite3数据库方面的知识,很多人(包括我)都在这里面有很多疑惑,成功完成这里面的部分例子之外,我会更多把我的体会和困惑提出来,一方面可能会解决大家共同的问题,一方面希望大家或者以后自己深入学习之后能够解答这些遗留的问题。两篇文章并不是对Heard First Python的抄写,因此也不对所解决的问题进行描述,更适用于学习过此书有困惑,希望讨论的人阅读。

第七章 web开发

采用MVC设计web应用,MVC即model-View-Controller,这样有助于将web应用的代码分解为易于管理的功能模块。

为数据建模

构建athletemodel.py函数用于对数据的存储和调用(包括pickle的应用),这个模块更多是对前6章基础知识的复习。

get_coach_data()
put_to_store()
get_from_store()

三个函数的定义分别代表了获取(处理)原始数据,存储数据,提取数据的作用。

设计网页界面

yate函数是Heard First Pyhon资源网站可以下载的代码,这部分代码已经部分超出了python的学习范围,主要用于生成用户界面的HTML,对的,就是应用python通过模板自动生成HTML文件。我们现在的目标是读懂代码,并可以修改关键信息,这里不在贴出代码。

控制器代码

书中推荐使用web应用的结构:
图片描述

这样的结构可以让我们更简单的管理自己代码和文件,其实我们随便打开一个软件的安装文件夹都可以看见类似的结构。

其次我们需要使用CGI(通用网关接口)脚本使网页运行,这类文件通常放在cgi-bin文件夹中:
generate_list.py文件用于生成选择选手名称界面HTML:

import athletemodel
import yate
import glob

data_files = glob.glob("data/*.txt")
athletes = athletemodel.put_to_store(data_files)

print(yate.start_response())
print(yate.include_header("Coach Kelly's List of Athletes"))
print(yate.start_form("generate_timing_data.py"))
print(yate.para("Select an athlete from the list to work with:"))

for each_athlete in athletes:
    print(yate.radio_button("which_athlete",athletes[each_athlete].name))
print(yate.end_form("Select"))
print(yate.include_footer({"Home":"/index.html"}))

generate_timing_data.py 文件用于生成 用户在选择选手后,响应返回该选手最快速度的三个时间:

import cgitb
cgitb.enable()

import cgi

import athletemodel
import yate

athletes = athletemodel.get_from_store() #从储存的数据中提取所需数据

form_data = cgi.FieldStorage()
athlete_name = form_data['which_athlete'].value

print(yate.start_response())
print(yate.include_header("Coach Kelly's Timing DAta"))
print(yate.header("Athlete:"+athlete_name+",DOB:"+athletes[athlete_name].dob+"."))
print(yate.para("THe top times for this athlete are:"))
print(yate.u_list(athletes[athlete_name].top3))
print(yate.include_footer({"Home":"/index.html","Select another athlete":"generate_list.py"}))

创建服务器

利用python创建自己的服务器:在webapp文件夹中打开cmd终端输入:python simple_httpd.py(打开此文件)即可以创建,就可以利用浏览器网址:http://localhost:8080 打开自己设计的网页。下面是simple_httpd.py的代码:

from http.server import HTTPServer, CGIHTTPRequestHandler

port = 8080

httpd = HTTPServer(('', port), CGIHTTPRequestHandler)
print("Starting simple_httpd on port: " + str(httpd.server_port))
httpd.serve_forever()

Tips:

1.glob函数可以方便的处理相同文件列表
2.

import cgitb
cgitb.enable()

用于追踪错误并显示在浏览器上,这对于寻找并修改错误有重要作用。
3.如果想要更好的理解本章内容,需要深入学习python在web开发方面的知识,如有错误或问题关系探讨,共同进步。

第8章 移动端开发(略)

android软件开发包书中的链接已经失效或者可能有墙,自己尝试安装了visual android开发,但很多配置和环境设置也是搞的自己晕头转向,最后模拟器最低支持android4.0版本,不过这也很正常,android开发本来就发展迅速,技术更新换代日新月异。这本书的一些资源和知识已经过时也是可以理解。因此我这里跳过了本书中关于Android开发的内容,在未来的学习中如果涉及android开发,我会寻找更好的资料或者项目进行学习。

第9章 处理输入(web部分)

本章是希望数据能够随着教练不断地方便地更新自己的数据,直接在网页中输入。

传建一个表单

首先创建一个HTML模板 templates/form.html

<form action = $cgi_name method = $http_method> #这里'$'后面的参数是通过另外程序可修改的
Enter a timing value: $list_of_inputs<br/>
<input type = "Submit" value = $submit_text>
</form>

接着,生成我们需要的html,在yate.py后增加代码:

def create_inputs(inputs_list):#取一个或多个字符串,为各个字符串创建HTML标记(不是很懂)
    html_inputs=''
    for each_input in inputs_list:
        html_inputs = html_inputs + '<input type = "Text" name="'+each_input+'"size=40>' 
    return(html_inputs)

def do_form(name,the_inputs,method="POST",text = "Submit"): #生成表单
    with open('templates/form.html') as formf:
        form_text = formf.read()
    inputs = create_inputs(the_inputs)
    form = Template(form_text)
    return (form.substitute(cgi_name=name,http_method = method,list_of_inputs=inputs,submit_text=text))

cgi-bin/test-form.py调用函数生成表单:

import yate

print(yate.start_response('text/html'))
print(yate.do_form ('add_timing_data.py',['TimeValue'],text='Send'))

add_timing_data.py 用于处理表单输入的数据:

import cgi
import os
import time
import sys
import yate

print(yate.start_response('text/plain'))
add = os.environ['REMOTE_ADDR']
host = os.environ['REMOTE_HOST']
method = os.environ['REQUEST_METHOD']
cur_time = time.asctime(time.localtime())
print(host + ","+ cur_time + ":"+ method+":",end='',file=sys.stderr)

form = cgi.FieldStorage()
for each_form_item in form.keys():
    print(each_form_item + '->'+form[each_form_item].value,end='',file=sys.stderr)
print(file=sys.stderr)
print('OK.')

输入数据的功能就完成了。
Tips:
1.我是在第7章开启服务器之后,输入网址http://localhost:8080/cgi-bin/test-form.py进入网站:
图片描述
2.在编写这个代码时,换了一个纯代码编辑器notpad++(之前用的vs)tab和space出现了混用报错:Tab Space Error 耽误了很多时间,提醒像我一样的在换新的编辑器时,记得设置tab=四个空格就好了。

数据库系统

使用Python预装sqlite3让我们很方便的使用数据库
首先编写创建空的数据库:

import sqlite3
connection = sqlite3.connect('coachdata.sqlite')
cursor = connection.cursor()
cursor.executescript("""
        CREATE TABLE athletes(
                  id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE,
                  name TEXT NOT NULL,
                  dob DATE NOT NULL);
                  """)
cursor.executescript("""
        CREATE TABLE timing_data(
                  athlete_id INTEGER NOT NULL,
                  value TEXT NOT NULL,
                  FOREIGN KEY (athlete_id) REFERENCES athletes)
                  """)
connection.commit()
connection.close()

其次通过initDBtables.py将data文件夹中的数据导入数据库:

import sqlite3

connection = sqlite3.connect('coachdata.sqlite')
cursor = connection.cursor()

import glob
import athletemodel

data_files = glob.glob("../data/*.txt")
athletes = athletemodel.put_to_store(data_files)

for each_ath in athletes:
    name = athletes[each_ath].name
    dob  = athletes[each_ath].dob
    cursor.execute("INSERT INTO athletes (name,dob) VALUES (?,?)",(name,dob))
    connection.commit()
    cursor.execute("SELECT id from athletes WHERE name=? AND dob=?",(name,dob))
    the_current_id=cursor.fetchone()[0]
    for each_time in athletes[each_ath].clean_data:
        cursor.execute("INSERT INTO timing_data (athlete_id,value) VALUES (?,?)",(the_current_id,each_time))
    connection.commit()
connection.close()

先将两文件放在cgi-bin文件夹中,然后在webapp中开启终端cmd,输入'py '然后将这两个文件拖入终端运行(或者输入位置和文件名达到同样效果),会在webapp文件夹中生成一个coachdata.sqlite文件,安装SQLiteManager进行查看:
图片描述

但不幸的是第二个文件并不能将数据传输到数据库中:
图片描述
这我卡住了好久未找到原因,代码中的提取数据部分应该没有问题,更多的是在和空数据库链接的问题上,但我并不知道怎么修改(自学数据库+1),于是这个问题就卡在这!我先把后面的流程走完。

数据库与第7章web应用进行集成

修改代码:
athletemodel.py:

import sqlite3

db_name = 'coachdata.sqlite'

def get_names_from_store():
    connection = sqlite3.connect(db_name)
    cursor = connection.cursor()
    
    results = cursor.execute("""SELECT name FROM athletes""")
    response = [row[0] for row in results.fetchall()]
    connection.close() 
    return(response)
    
def get_athlete_from_id(athlete_id):
    connection = sqlite3.connect(db_name)
    cursor = connection.cursor()
    
    results = cursor.execute("""SELECT NAME,dob FRCM athletes WHERE id=?""",(athlete_id,))
    (name,dob) = results.fetchone()
    results = cursor.execute("""SELECT value FROM timing data WHERE athlete id=?""",(athlete_id,))
    data = [row[0] for row in result.fetchall()]
    response = {    'name': name,
                    'DOB' : dob,
                    'data': data,
                    'top3':data[0:3]}
    connection.close()
    return(response)
    
    
def get_namesID_fromstore():
    connection = sqlite3.connect(db_name)
    cursor = connection.cursor()
    results = cursor.execute("""SELECT name,id FROM athletes""")
    response = results.fetchall()
    connection.close() 
    return(response)

修改generate_list。py代码,适应sqlite3数据库:

import athletemodel
import yate



athletes = athletemodel.get_namesID_from_store()

print(yate.start_response())
print(yate.include_header("NUAC's List of Athletes"))
print(yate.start_form("generate_timing_data.py"))
print(yate.para("Select an athlete from the list to work with:"))

for each_athlete in athletes:
    print(yate.radio_button_id("which_athlete",each_athlete[0],each_athlete[1]))#注意这里增加了一个radio_button_id()函数。
print(yate.end_form("Select"))
print(yate.include_footer({"Home":"/index.html"}))

修改generate_timing_data代码:

import cgi

import athletemodel
import yate


form_data = cgi.FieldStorage()
athlete_name = form_data['which_athlete'].value
athlete = athletemodel.get_athlete_from_id(athlete_id)

print(yate.start_response())
print(yate.include_header("NUAC's Timing DAta"))
print(yate.header("Athlete:"+athlete['name']+",DOB:"+athlete['DOB']+"."))
print(yate.para("THe top times for this athlete are:"))
print(yate.u_list(athlete['top3']))
print(yate.para("The entire set of timing data is:"+str(athlete['data'])+"(duplicates removed)."))
print(yate.include_footer({"Home":"/index.html","Select another athlete":"generate_list.py"}))

在yate中增加新的radio_button_id按钮:

def radio_button_id(rb_name, rb_value, rb_id):
    return('<input type="radio" name="'+ rb_name +'"value="'+str(rb_id)+'">' + rb_value + '<br/>')

这样新的数据库就与第7章的web项目集成到一起了,通过书上的讲解理解应该不成问题,但因为我的数据库问题没法解决,所以在尝试新web应用时,得到了死亡空白,感觉这里也是有问题的,看来能通过后面的学习,再回来修改了(有同学发现解决方案希望留言探讨,感激不尽!)。

第10章 利用google app Engine 开发web应用:

需要翻墙,暂时不研究。

第11章 总结

结合书中最后的附录,总结一些我在这期间学到的一些小知识

  1. 我开始用的是IDLE编写和调试代码,后来使用的是notepad++,vscode和pychram编写和调试这也是我调查了资料和亲自上手测试认为最适合两款软件。
  2. 全局变量无法正常修改,除非增加语句'global xxxx '其中xxx为全局变量。
  3. 匿名函数,生成器,定义异常,元类,正则表达式 GUI编程,全局解释器锁在后面的学习中如果有涉及,我会回来添加。
  4. 关于这本书的评价,这是一部极好的python入门学习书籍,但要熟练的使用python不能仅限于此,在学习完这部书之后,我会继续学习其他python的书籍或者follow一些开源项目,使自己对着门语言更加熟悉,但请对我有些信心,掌握这门语言没有想象的那么难。这里贴出这本书的资源网站:http://python.itcarlow.ie/res... 如果需要关于这本书的源代码或者有任何问题都可以留言私信,欢迎探讨大家共同进步。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值