1. 程式人生 > >python練習冊第二題

python練習冊第二題

題目

將 0001 題生成的 200 個啟用碼(或者優惠券)儲存到 MySQL 關係型資料庫中。

解決思路

基本步驟應該是:讀取檔案 --> 解析字元 --> 開啟資料庫 --> 存入後關閉。其中涉及python操作mysql資料庫的我還不是很熟悉。

py3.6我是用pymysql作為驅動的,語法基本上和廖大提到的mysql-connector差不多,個別地方需要有所改動。
pymysql操作資料庫的基本套路就是連線資料庫,連線資料庫遊標,再通過遊標的execute語句執行mysql操作。

解決程式碼

自覺寫得好爛……只是應付題目就不要要求太高了吧。


import base64
import re
import pymysql

def parser(line):
    return base64.b64decode(line).decode()

def re_split(s):
    list = re.split(r'[\:\/]+', s)
    dict = {
        list[0]: list[1],
        list[2]: list[3]
    }
    return dict

def connect():
    conn = pymysql.connect(host='localhost', port=3306,db='test', user='***', password='***') # 根據實際填
    cur = conn.cursor()
    sql_create = "create table if not exists `coupon` (`id` varchar(20), `goods` varchar(20))"
    # cur.execute(sql_create)
    return cur, conn
    
def insert(cur, dict):
    sql = 'insert into coupon (id, goods) values ({id}, {goods})'
    cur.execute(sql.format(id=dict['id'], goods=dict['goods']))


if __name__ == '__main__':
    cur, conn = connect()
    with open('C:/Users/ChanWunsam/Desktop/coupon.txt', 'r') as fp:
        for line in fp.readlines():
            s = parser(line)
            dict = re_split(s)
            print(dict)
            insert(cur, dict)
        conn.commit() # 特別需要注意
        conn.close()
        

別人的思路

這道題沒有需求,我也不知道要怎樣才好。這位大神估計是經歷過實踐的,把啟用碼的id、有效時間、所有者和啟用碼本身都存入進去了。emmm,我壓根就不知道有這麼多東西。
還有就是程式碼看上去確實賞心悅目,我個人是這麼覺得的。默默學習了~


import base64
import re
from sqlalchemy import Column, String, DATE, create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

database_info = {
    'user': '',
    'passwd': '',
    'ip': '',
    'port': '',
    'database': ''
}


class Coupon(Base): 
    __tablename__ = 'coupon'

    id = Column(String(200), primary_key=True)
    deadline = Column(DATE)
    userID = Column(String(200))
    code = Column(String(200))


def make_connect(DB_info):  # mapper
    connect_str = 'mysql+pymysql://{user}:{passwd}@{ip}:{port}/{database}'.format_map(DB_info)
    engine = create_engine(connect_str) 
    DBSession = sessionmaker(engine)
    session = DBSession()
    return session


def parse_coupon(c_code):
    return base64.urlsafe_b64decode(c_code.encode('utf-8'))


def upload_to_database():
    session = make_connect(database_info)
    with open('coupon.txt', 'r') as file:
        for line in file.readlines():
            c_id = re.findall(r'.*/.*:(.*)\'', str(parse_coupon(line)))
            session.add(Coupon(id=c_id.pop(), code=line))
        session.commit()
        session.close()

if __name__ == '__main__':
    upload_to_database()

關於sqlalchemy

廖大的教程

sqlalchemy介紹和示例--英文

There are three most important components in writing SQLAlchemy code:

  • A Table that represents a table in a database.
  • A mapper that maps a Python class to a table in a database.
  • A class object that defines how a database record maps to a normal Python object.

Instead of having to write code for Table, mapper and the class object at different places, SQLAlchemy's declarative allows a Table, a mapper and a class object to be defined at once in one class definition.

廖大的示例:

#第一步,匯入SQLAlchemy,並初始化DBSession:

# 匯入:
from sqlalchemy import Column, String, create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

# 建立物件的基類:
Base = declarative_base()

# 定義User物件:
class User(Base):
    # 表的名字:
    __tablename__ = 'user'

    # 表的結構:
    id = Column(String(20), primary_key=True)
    name = Column(String(20))

# 初始化資料庫連線:
engine = create_engine('mysql+mysqlconnector://root:[email protected]:3306/test')
# 建立DBSession型別:
DBSession = sessionmaker(bind=engine)

#以上程式碼完成SQLAlchemy的初始化和具體每個表的class定義。如果有多個表,就繼續定義其他class,例如School:

class School(Base):
    __tablename__ = 'school'
    id = ...
    name = ...

#由於有了ORM,我們向資料庫表中新增一行記錄,可以視為新增一個User物件:

# 建立session物件:
session = DBSession()
# 建立新User物件:
new_user = User(id='5', name='Bob')
# 新增到session:
session.add(new_user)
# 提交即儲存到資料庫:
session.commit()
# 關閉session:
session.close()

基本和官網示例差不多,就是官網的看得一愣一愣的。


easy_install

今天本來想重現下大神的程式碼,發現包還沒裝。不知什麼原因pip install行不通,cdsitepackage資料夾,使用easy_install又可以了,就記錄一下。

既然用了,總要學點東西。pip最早應該是Linux裡的,之前win用的都是easy_install。不過現在easy_installpip都是用來下載安裝Python一個公共資源庫PyPI 的相關資源包的pipeasy_install的改進版,提供更好的提示資訊,刪除package等功能。老版本的python中只有easy_install,沒有pip

復現發現的問題

在復現大神程式碼時候,發現報錯pymysql.err.ProgrammingError: (1146, "Table 'test.coupon' doesn't exist"),表沒有建立。上網查了一下,有人問一模一樣的問題,是少了一個語句Base.metadata.create_all(engine).

session.add()是建立在資料庫中已經有對應table的基礎上了,所以需要先對資料庫進行表的建立:Base.metadata.create_all(engine)。現在就沒問題了。