3

实验楼楼赛第3期-Python-题解

 2 years ago
source link: https://changkun.de/blog/posts/%E5%AE%9E%E9%AA%8C%E6%A5%BC%E6%A5%BC%E8%B5%9B%E7%AC%AC3%E6%9C%9F-python-%E9%A2%98%E8%A7%A3/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

因对 Python 感兴趣,于是早上吃早饭时看看。题目相对比较简单,最后一题代码写得比较随意。原本打算交上去测试一下,可惜海外党使用环境实在是卡得惨不忍睹,没办法写敲那么多代码上去。

题目:https://www.shiyanlou.com/contests/lou3/challenges

题目1: 存储学习记录

出现的问题:

  • sqlite url schema 错误
  • 外键设置错误
  • 外键重复设置

解决方法:

  • line 10: sqlite:// 改为 sqlite:///
  • line 22: backref='user' 改为 backref='course'
  • 表设计为一对多的外键,故注释掉 line 28 & line 30

题目2: 追踪课程更新

出现的问题:

  • 缺少 object 基类
  • 缺少子类初始化
  • @property 方法访问错误
  • typename 缺少参数
  • 浅拷贝错误

解决方法:

  • line 5: 改为 class Course(object)
  • line 21: 给 typename 传递参数 self
  • line 28: 替换为 super(BootcampCourse, self).__init__(name, True, lab_count)
  • line 37: 改为调用 self.lab_count
  • line 29: 改为调用 copy.deepcopy

题目3: 修复 Internal Server Error

出现的问题:

  • filter_by 用法错误
  • html 模板错误

解决方法:

  • app/main/views.py line 34: filter_by(id=id).first_or_404()
  • app/templates/todolist.html line 4: for('static', filename='js/todolist.js')
  • app/templates/todolist.html line 9: {{todolist.title|title}}

题目4: NoSQL 的艺术

潜在的问题:

  • 从 bash 中读入的值为字符串
  • mongodb 的 aggregate pipeline 操作
  • sort 结果搜索: mongodb 的 aggregate 操作找了半天实在没找到如何从操作结果的 cursor 拿到排名,只得做如下妥协处理,读者可继续探究
# TODO: return the rank of user_id
user_id = int(user_id)    
results = contests.aggregate([
  {
    '$group': {
      '_id': '$user_id', 
      'sum_score': {'$sum': '$score'}, 
      'sum_time': {'$sum': '$submit_time'}
    }
  },
  {
    '$sort': {
      'sum_score': -1,
      'sum_time': -1
    }
  }
])
# CRISES: id_list may cause large memory consumption
id_list = [int(value['_id']) for value in results]
# INPROVEMENTS: could use binary search
try: return id_list.index(user_id)+1
except: return 0

题目5: 增加服务器管理功能

潜在的问题:

  • 异常处理方式: 异常处理的部分原题目似乎并未写指示清楚, 这里用直接抛出 ScriptError 异常做处理
  • csv 文件处理: 虽然其实并不是 csv 格式,但由于带空格的形式可以视为 csv 文件进行处理; 另一方面文件操作似乎并不支持单独一行的处理操作?
  • 重复添加操作判断: 重复添加的判断逻辑应为: 当 hostip 和 user 同时相同时,则不能添加,否则可添加。
  • 命令行参数处理: 最初决定使用 argparse 处理命令行参数,扫文档扫了半天没搞明白怎么添加 subparameter requirement,google 了一阵也很奇怪,最后还是决定直接暴力解包判断了
import sys
import csv

class ScriptError(Exception):
  def __init__(self, value):
    self.value = value
  def __str__(self):
    return repr('ERROR:'+self.value)

def listinfo():
  with open('serverinfo', 'rb') as csvfile:
    reader = csv.reader(csvfile, delimiter=' ')
    for row in reader:
      print ' '.join(row)

def addinfo(hostip, user, password):
  with open('serverinfo', 'r+') as csvfile:
    reader = csv.reader(csvfile, delimiter=' ')
    contents = []
    new = [hostip, user]
    for row in reader:
      contents.append([row[0], row[1]])
    if new not in contents:
      writer = csv.writer(csvfile, delimiter=' ')
      writer.writerow([hostip, user, password])
    else:
      raise ScriptError('user exists')

def deleteinfo(hostip):
  f = open('serverinfo', 'r')
  lines = f.readlines()
  f.close()
  f = open('serverinfo', 'w')
  for line in lines:
    if hostip not in line:
      f.write(line)
  f.close()

def main():
  if len(sys.argv) < 2:
    print """
    Usage:
    ======
    python server.py [add|delete|list]
    
    add: add info, required parameter below
         -h hostip
         -u user
         -p password
    delete: delete info, required parameter below
         -h hostip
    list:list all info
    """
  elif sys.argv[1] == 'add':
    if (sys.argv[2] == '-h' or sys.argv[2] == 'hostip')   and \
       (sys.argv[4] == '-u' or sys.argv[4] == 'user')     and \
       (sys.argv[6] == '-p' or sys.argv[6] == 'password') and \
       len(sys.argv) == 8:
      addinfo(sys.argv[3], sys.argv[5], sys.argv[7])
    else:
      raise ScriptError('argument error')
  elif sys.argv[1] == 'delete':
    if (sys.argv[2] == '-h' or sys.argv[2] == 'hostip') and len(sys.argv) == 4:
      deleteinfo(sys.argv[3])
    else:
      raise ScriptError('argument error')
  elif sys.argv[1] == 'list':
    listinfo()
  else: raise ScriptError('no such option')

if __name__ == '__main__':
  main()

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK