GithubHelp home page GithubHelp logo

hysic / omooc2py Goto Github PK

View Code? Open in Web Editor NEW

This project forked from aihackers/omooc2py

0.0 0.0 0.0 0 B

https://www.gitbook.com/book/hysic/hysic-s-python-journey/details

License: MIT License

Python 81.71% Smarty 14.00% CSS 4.30%

omooc2py's People

Contributors

hysic avatar omclub avatar

Watchers

 avatar  avatar  avatar

omooc2py's Issues

3w 任务

日记系统 net 版

~ 任务需求

  • 每次运行时合理的打印出过往的所有笔记
  • 一次接收输入一行笔记
  • 在服务端保存为文件:
    • 在所有访问的客户端可以获得历史笔记
  • 支持多个客户端同时进行笔记记录

任务开发记录

  • socket 模块官方文档看的一头雾水, 对于我这样对 socket 没有基本常识的小白来说,通读一遍基本是一头雾水, 只好暂且放下, 留待后面查看.

  • google python socket udp, 找到python wiki 中的 UDP Communication, 以及PyMOTW 上的User Datagram Client and Server, 二者的优点都是提供了一个创建 UDP server 和 client 的最小脚手架, 可以在此基础上添加自己需要的功能.

  • 我主要以PyMOTW 上的User Datagram Client and Server为脚手架完成本周的任务.

    • server 端
    import socket
    
    # create a UDP server socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    
    # bind the socket to the server address
    server_address = ('localhost', 10001)
    sock.bind(server_address)
    
    # receive the data and the client address
    data, client_address = sock.recvfrom(1024)
    • client 端
    import socket
    
    # create a UDP client socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    
    server_address = ('localhost', 10001)
    message = 'This is the message.'
    
    # send the message to the server
    sent = sock.sendto(message, server_address)
    
    # close the socket
    sock.close()
  • 如此即可完成 server 和 client 之间的一次数据传送, 接下来以此为基础, 增加任务需求功能.

    每次运行时合理的打印出过往的所有笔记

    • 相当于从 server 端向 client 端传送数据, 在 server 端已经获取到 client_address, 只需要在 server 端增加 sent = sock.sendto(message, client_address) , client 端增加 data, server = sock.recvfrom(1024) .

    一次接收输入一行笔记

    • client 端增加 while True 无限循环, 利用raw_input() 函数提示用户输入.

    在服务端保存为文件
    在所有访问的客户端可以获得历史笔记

    • 这与前两周的任务要求并无二致, 文件基本读写操作, 采用 with open("diary.log", "a+") as f:, 输入一行保存一行.

    支持多个客户端同时进行笔记记录

    • 这似乎是 UDP 协议的特性,
  • 接下来就是在 client 端增加一些默认参数, h/help/? 显示帮助, r/sync 显示历史记录, q/quit 退出 socket.然后用 if/elif/else 语句进行条件判断.

  • 具体代码及代码说明见 https://github.com/hysic/OMOOC2py/tree/master/_src/om2py3w/3wex0.

  • 任务需求的功能基本实现了, 下面看看任务代码具体是什么意思.

啥是 socket?

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

  • python 中 socket 对象初始化时有两个参数, 第一个是 address famlily, 用来声明 OSI 模型中网络层的协议, 常见的就是 AF_INET, 即为 IPv4; 第二个是 socket type, 用来声明 OSI 模型中传输层的协议, 常见的有两种, SOCK_DGRAM 用于 UDP 协议, SOCK_STREAM 用于 TCP 协议.
  • socket 是计算机进程间通信(IPC)的一种(其他的还有??), 可以跨操作系统. 比如现在绝大部分计算机之间通过 IP 协议互相通信, 因此绝大部分 socket 都是 Internet Socket.
  • socket 翻译成汉语为插座, 在计算机领域翻译成套接字, 根据知乎的启发, 参见socket pipe 的 google 图片搜索, 可以对 socket 的接口作用有一个直观地理解.

啥是 C/S 架构?

  • Client/Server 架构(主从式架构), 是一种常见的软件架构模型, 我们日常所接触的网络基本都是 C/S 架构的, 如互联网, E-mail, 网络游戏, 微信.

  • 与之相对的结构方式为 P2P(peer-to-peer)架构.

  • server 端的 socket 对象需要绑定(bind)一个 socket 地址. 一个 socket 地址包括一个 IP 地址和一个端口号(port number). 比如运行下面的代码:

    import socket
    print socket.getaddrinfo("www.python.org", "http")

    即可得到

    [(2, 2, 17, '', ('103.245.222.223', 80)),
    (2, 1, 6, '', ('103.245.222.223', 80))]
    

    ('103.245.222.223', 80)就是 HTTP 连接 python 官网的 socket 地址.

啥是 UDP?

用户数据报协议(英语:User Datagram Protocol,缩写为 UDP),是一个简单的面向数据报的传输层协议,正式规范为 RFC 768.
UDP只提供数据的不可靠传递,它一旦把应用程序发给网络层的数据发送出去,就不保留数据备份.

  • UDP vs TCP
    • TCP 更加可靠, 不会丢失数据, 数据是顺序传输的;
      UDP 更加快速, 支持, 允许丢包和乱序.
    • TCP server 端需要先建立 socket, 然后 bind → listen → accept 一系列操作, 才能和客户端发送/接收数据;
      client 端需要先建立 socket, 然后 connect 到制定 socket 地址, 才能和服务器端发送/接收数据.
      发送/接收数据采用 send/recv 方法.
      TCP 流程图
    • UDP server 端建立 socket, 与 server 地址绑定(bind)后即可与客户端发送/接收数据.
      client 端只需建立 socket 即可与服务器发送/接收数据.
      发送/接收数据采用 sendto/recvfrom 方法, sendto 需制定 socket 地址.
  • UDP 传输何种情况下会丢包或乱序??
    • 我本地传送了一个 pdf 文件, 将其作为二进制文件打开, 然后传输, 传输结果目测没有任何问题. (我相当于花了十几分钟完成了一个9MB pdf 的复制)

进一步任务

  • 保存笔记的客户端来源? 并输出不同客户端提交的笔记?
  • multicasting??

1W 任务交作业

极简日记系统

~ 本文 gitbook 地址: https://hysic.gitbooks.io/hysic-s-python-journey/content/1sTry/Week_1/Interactive101.html

任务要求

完成一个极简交互式日记系统,需求如下:

  • 一次接收输入一行日记
  • 保存为本地文件
  • 再次运行系统时,能打印出过往的所有日记

代码仓库

开发过程

~ 芝麻星中"第一周行动"卡包中已经将任务进行初步分解, 我主要按照分解的任务依次进行, 必要时做进一步任务分解.

脚本调用

  • 创建.py文件,每次在CLI中以python main.py运行之。
只有 .py 的文件才是我们应该持续修订的开发容器.
    ——ZoomQuiet

调用参数

  • 采用命令行参数(Command Line Arguments)
  • import sys
  • 调用方法: python main.py argv1 argv2 ...
  • main.py是第一个参数
  • 参数个数与main.py中定义的个数相同, 参数过多或过少都会产生ValueError

输入中文

  • python main.py 中文 未出现异常.

持续交互

一次接收输入一行日记

~ 这里开始解决任务需求, 将任务需求进一步拆分.
~ 这里需要解决两个问题, 一个是持续运行, 等待继续输入或退出; 一个是如何退出.

  • 持续运行
    • 不想每输入一句话都提示是否要继续
    • while True 循环
    • 注意一定要退出
  • 退出方式:
    • 希望 control-Ccontrol-D 退出
    • 注意: except KeyboardInterupt 之后一定要 break, 否则无法退出无限循环
    • 另一种退出方式是 sys.exit(exit_message), 无须 break
    • 小问题: 在用 control-C 退出时,会在 exit_message 前多了一个^C字符.

输出为文件

保存为本地文件

~ 这里可进一步拆分为文件打开, 文件读取, 文件读入, 文件保存关闭.

  • 文件打开
    • open(file_name, mode)
    • 文件读入
    • file.write(message)
    • 运行发现file.write并不会写入换行符
    • 注意要写入换行符'\n'
  • 文件关闭
    • file.close()
    • 一定要在退出前关闭文件
    • 不关闭会怎样?
    • 是否自动保存?

回读文本数据

再次运行系统时,能打印出过往的所有日记

~ 任务进一步分解: 确认文件内容不为空, 文件读取并print

增加时间

  • 简单实现

    import time
    print time.asctime() # or time.ctime()
    • 优点: 代码少
    • 缺点: 输出时间格式固定, 可用字符串拆分重组

开发心得

  • 本周任务卡片中已经帮我们把任务分解, 这给我们做了一个很好的示范, 以后即使没有我们也要自己对任务进行分解, 先分解成大块, 大块完成不了就再进一步细分, 这样一步一步完成心里会比较踏实
  • 要努力克服完成一小步所产生的巨大的膨胀感, 以及由此产生的想关掉编辑器干点别的的念头.
  • 遇到长篇英文文档就不想读, 需改进方法?
  • @一休君所说的 https://docs.python.org/2/index.html 中的快速搜索框是个好东西.

下一步任务

  • 任务中说"先不管数据结构", 这是什么意思?
  • 中文编码问题? 尚未遇到坑
  • time 格式的定制输出, e.g. 2015-10-21 16:43
  • 阅读材料中推荐的DOCOPT的作用?

[4w 任务]日记系统 Web 版

~ 任务需求

  • 通过网页访问系统:
    • 每次运行时合理的打印出过往的所有笔记
    • 一次接收输入一行笔记
    • 在服务端保存为文件
  • 同时兼容 3w 的 Net 版本的命令行界面进行交互

~ 任务代码及说明: https://github.com/hysic/OMOOC2py/tree/master/_src/om2py4w/4wex0

任务开发记录

Bottle 框架

  • 上下班路上通读Bottle 官网 tutorial, 只是对 bottle 的功能有个大概的印象, 但对本周作业如何实现依然没什么思路.

    • 直到我读到了官网上的这个 Tutorial: Todo-List Application以及大妈的这个 Simple-todo Bottle 实现版, 终于有了个模仿对象, 至少可以照葫芦画瓢完成任务了.
    • 说起官网文档看不懂的问题, 上次大妈也问过我这个问题. 我觉得是我的需求和官方文档不是一个思路. 我的需求是需要对小白从最基础的概念讲起, 每个概念都最好配上详细实例, 然后层层递进, 直至更复杂的实例. 而 Bottle 官网的 Tutorial 则力求做到面面俱到, 每一点特性都要顾及到, 反而没有什么重点. 对比下面用到的 requests 模块的官方文档, 则比较对我的胃口, 显示 Quickstart, 帮助你快速上手, 然后是 Advanced Usage, 讲一些进阶用法, 适合于不同程度的用户. 所以我目前的看法是, 官方文档不可不看, 但若不对口味, 可以 google 寻找其他对口味的教程, 先入门了再说.
    • 现在再回头看Bottle 官网 tutorial, 对里面的一些术语有了基本的概念, 所以对里面的内容也有了更多地理解, 所以官方文档即使开始看不懂, 在其他地方入门了之后也一定要回读官方文档.
  • Bottle 框架的几个函数
    ~ 创建网页, 简单地说就是URL地址 + 网页内容(HTML+CSS+JS), 再就是与服务器的数据交互, Bottle 框架有几个函数分别做这几项事情.

    • route 路由, Bottle 中最重要的一个函数, 将 URL 与一个函数关联, 该函数的返回值则是这个 URL 对应网页的显示内容. 更重要的是, 这个 URL 可以是动态的, 可以用正则表达式涵盖好多类似的 URL 地址. route 还可以指定http 请求方法, 默认是 GET.

      @route('/diary')
      def show_diary():
          return template("write_diary.tpl", diary_file=filename)

      比如这段代码对应的 URL 就是/diary, 网页显示的内容就是 write_diary.tpl 这个模板里面的内容.

    • template 模板, 将 html 分离成一个单独的文件, 可以多次使用, 可以缓存, 同时还可以传入一些需要修改的参数. Bottle 内置了 Simple Template 引擎, 足够完成本周任务. 大妈推荐的 Jinja2 模板引擎, 留待后续使用.

    <form action='/diary' method="POST">
        <input type="text" size="100" maxlength="100" name="new_line" autofocus>
        <input type="submit" name="save" value="保存">
    </form>
    
    <div id="diary_content">
    %with open(diary_file) as f:
        %for line in f:
            <p>{{line[0: -1]}}</p>
        %end
    %end
    </div>

    这段代码就是我实现本周任务使用的模板, 注意到最后一个 div 里还有几行以%开头的 python 代码, 模板是允许这种写法的, 可以在模板内插入 if, for 等语句.

    • request, 用于服务器端和客户端之间交换数据, 比如 new_line = request.POST.get('new_line', '') 用于从网页中名为 new_line 的 input 元素中获取客户端的输入内容.
    • run, 服务器运行, 默认地址是 localhost, 默认端口是 8080. 添加 reloader=True 参数可以在在修改代码后不用重启服务器, 对调试代码很有用, 但在上线后一定要删除.
    • debug, 调试, 可以在网页端直接显示报错信息.
  • 最终实现的网页界面是这样婶的.

CLI 交互

  • 本周任务还有一个要求:

同时兼容 3w 的 Net 版本的命令行界面进行交互

  • 我开始的想法是, 把3w client 端的代码直接拿来用. 创建一个 TCP socket, 连接 localhost:8080/diary, 然后 recv 数据, 可以毫无动静. 因为我服务器端并没有设置要向客户端 send 数据, 一切都是 bottle 封装好的 http 协议.
  • 看了一下其他同学的代码, 发现 很多都用了 requests 模块, google 之, 很diao.

Requests: HTTP for Humans

  • 而且 requests 的文档写的比较符合我的胃口, Quickstart 页面就满足了我的全部要求(读数据, 发送数据), 大赞!
import requests
# get the request data from the server page
r = requests.get("127.0.0.1:8080/diary")
print r.content
# post data to the server
rw = requests.post("127.0.0.1:8080/diary", data = {'new_line': "some_message"})
  • 这样输出的是包含 html 标签在内的全部网页内容, 需要进一步去除标签, 找到自己需要的那部分网页内容. google python html, 找到 Python Guide 的这个页面, 里面介绍了 requests 模块, 还有 lxml 模块, 刚好就是我需要的!! 而且, lxml 模块一共介绍了三行代码, 刚好可以完成我的要求, 太赞了!
import requests
from lxml import html
# get the request data from the server page
r = requests.get(server_address)
# parse the page content into a nice tree structure
tree = html.fromstring(r.content)
# use XPath to get to the html section you want
diary_content = tree.xpath('//div[@id="diary_content"]/p/text()')
print diary_content

任务回顾

  • 其实我感觉最大的难点不在代码本身, 而在于网站的架构, 需要有几个页面, 每个页面的 getpost 方法分别对应什么. 虽然最后只用了一个 URL, 但那是因为网站本身不复杂, 要是复杂一点, 比如做一个 todo list 网站, 就需要像大妈那样做 URI 设计了.

下一步工作

  • KVDB
  • RESTful??

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.