1.arrow
Arrow提供了一個(gè)合理的、人性化的方法來創(chuàng)建、操作、格式轉(zhuǎn)換的日期,時(shí)間,和時(shí)間戳,幫助我們使用較少的導(dǎo)入和更少的代碼來處理日期和時(shí)間。
安裝
pip install arrow
常用方法案例:
# -*- coding: utf-8 -*-
import arrow
'''1.獲取當(dāng)前時(shí)間'''
print(arrow.utcnow()) # 獲取當(dāng)前utc時(shí)間
print(arrow.now()) # 獲取當(dāng)前系統(tǒng)時(shí)間
'''2.將時(shí)間戳轉(zhuǎn)化為arrow對(duì)象 時(shí)間戳可以是int,float或者可以轉(zhuǎn)化為float的字符串'''
print(arrow.get(1556073222))
print(arrow.get('1556073222'))
print(arrow.get(1556073222.264))
print(arrow.get('1556073222.264'))
'''將字符串轉(zhuǎn)換為arrow對(duì)象 arrow.get(string[,format_string])'''
print(arrow.get('2019-04-24 10:43:30','YYYY-MM-DD HH:mm:ss'))
print(arrow.get('2019-04-24T10:00:00.000-07:00')) # 循ISO-8601的字符串不需要格式字符串參數(shù)即可轉(zhuǎn)換
print(arrow.get('June was born in December 1994', 'MMMM YYYY')) # 可以從字符串中通過格式參數(shù)搜索時(shí)間
print(arrow.get(2019, 4, 24)) # 直接創(chuàng)建arrow對(duì)象
print(arrow.Arrow(2019, 4, 24)) # 直接創(chuàng)建arrow對(duì)象
'''arrow對(duì)象屬性 datetime,timestamp,tzinfo'''
time_msg = arrow.now()
print(time_msg.datetime)
print(time_msg.timestamp) # 時(shí)間戳
print(time_msg.naive)
print(time_msg.tzinfo) # 時(shí)區(qū)
print(time_msg.hour) # 小時(shí)
print(time_msg.day) # 日期(天)
'''時(shí)間推移 a.shift(**kwargs)'''
print(time_msg.shift(days=-1)) # 前一天
print(time_msg.shift(weeks=+1)) # 一周后
print(time_msg.shift(weekday=6)) # 距離time_msg最近的一個(gè)星期日,weekday從0到6代表周一到周日
'''時(shí)間替換 a.replace(**kwargs)'''
print(time_msg.replace(hour=6)) # 將小時(shí)替換為6
'''格式化輸出 a.format([format_string])'''
print(time_msg.format())
print(time_msg.format('YYYY-MM-DD HH:mm:ss ZZ'))
2. toolz
安裝
pip install toolz
案例
# -*- coding:utf-8 -*-
'''
1.純函數(shù)
(1).它不依賴于隱藏狀態(tài),或等效的取決于它的輸入。
(2).功能評(píng)估不會(huì)引起副作用
簡(jiǎn)而言之,純函數(shù)的內(nèi)部工作與程序的其余部分是隔離的。
'''
# 純函數(shù)
def min(x,y):
if x<y:
return x
else:
return y
# 非純函數(shù)
exponent = 2
def powers(L):
for i in range(len(L)):
L[i] = L[i]**exponent
return L
if __name__ == '__main__':
result1 = min(6,10)
data = [1,2,3]
result2 = powers(data)
print(result1)
print(result2)
# min()函數(shù)的功能很純粹,在給定相同輸入?yún)?shù)的情況下,它的產(chǎn)生的結(jié)果始終是相同的。
# powers()函數(shù)的輸出結(jié)果是受到全局變量exponent影響的,因此是不純的。
'''
2.惰性迭代器
惰性迭代器僅在必要時(shí)進(jìn)行評(píng)估。它們?cè)试S我們?cè)谡Z義上操作大量數(shù)據(jù),同時(shí)在內(nèi)存中
保留很少的數(shù)據(jù)。它們像列表一樣,但不占用空間。
'''
# 打開一個(gè)文件,python打開這個(gè)文件,但是不讀取任何一行文本,對(duì)象book就是一個(gè)惰性迭代器。
# 當(dāng)我們調(diào)用next()讀取文件內(nèi)容時(shí),book迭代器會(huì)在文本中慢慢前進(jìn)
book = open('book_of_tools.txt')
print(next(book)) # 第一行
print(next(book)) # 下一行
# 我們可以懶惰地操作惰性迭代器而不進(jìn)行任何實(shí)際計(jì)算
from toolz import map
loud_book = map(str.upper,book)
print(next(loud_book)) # 第一行
print(next(loud_book)) # 下一行
# 我們經(jīng)常使用懶惰來避免一次將大數(shù)據(jù)集加載到內(nèi)存中。對(duì)大型數(shù)據(jù)集的許多計(jì)算不需要一次訪問所有數(shù)據(jù)。
# 如下是計(jì)算文本中的所有字母。
from toolz import concat, frequencies
letters = frequencies(concat(loud_book))
print(letters)
'''
3.Curry
curried函數(shù)部分評(píng)估它是否沒有收到足夠的參數(shù)來計(jì)算結(jié)果
'''
from toolz import curry
@curry
def mul(x,y):
return x*y
double = mul(2,2)
print(double)
3. peewee
安裝
pip install peewee
案列
# -*- coding:utf-8 -*-
from peewee import *
'''
Peewee 是一個(gè)簡(jiǎn)單、輕巧的 Python ORM。
簡(jiǎn)單、輕巧、富有表現(xiàn)力(原詞 expressive )的ORM
支持python版本 2.6+ 和 3.2+
支持?jǐn)?shù)據(jù)庫包括:sqlite, mysql and postgresql
包含一堆實(shí)用的擴(kuò)展在 playhouse 模塊中
'''
'''
1.模型定義
賓語 對(duì)應(yīng)...
模型類 數(shù)據(jù)庫表
字段實(shí)例 在桌子上的列
模型實(shí)例 在數(shù)據(jù)庫表中的行
'''
db = SqliteDatabase('people.db')
# 創(chuàng)建Person模型類
class Person(Model):
name = CharField()
birthday = DateField()
class Meta:
database = db
# 創(chuàng)建Pet模型類
class Pet(Model):
owner = ForeignKeyField(Person,backref='pets')
name = CharField()
animal_type = CharField()
class Meta:
database = db
# 創(chuàng)建數(shù)據(jù)存儲(chǔ)標(biāo)表
db.create_tables([Person,Pet])
'''
2.存儲(chǔ)數(shù)據(jù)
通過save()和create()方法添加和更新記錄
'''
from datetime import date
old_wang = Person(name='wangyifan', birthday=date(1994,12,15))
old_wang.save()
# 使用create()方法添加人員
old_zhao = Person.create(name='zhaoyi', birthday=date(1996,3,13))
old_liu = Person.create(name='liuxing', birthday=date(1995,2,23))
# 更新數(shù)據(jù)時(shí),可修改模型實(shí)例后調(diào)用save()方法保存更改
old_zhao.name = 'zhaoxue'
old_zhao.save() # 保存修改
print(old_zhao.name)
# 為人員分配寵物
wang_lucky = Pet.create(owner=old_wang, name='lucky', animal_type='dog')
zhao_ww = Pet.create(owner=old_zhao, name='ww', animal_type='dog')
# 刪除寵物
zhao_ww.delete_instance()
# 將寵物分配給其他人
wang_lucky.owner = old_zhao
wang_lucky.save()
print(wang_lucky.owner.name)
'''3.數(shù)據(jù)檢索'''
# 從數(shù)據(jù)庫獲取單個(gè)記錄 select.get()
person_a = Person.select().where(Person.name == 'wangyifan').get()
print(person_a.name,"person_a.name")
person_a = Person.get(Person.name == 'wangyifan') # 簡(jiǎn)化寫法
print(person_a.name,"person_a.name,")
# (1)記錄列表
for person in Person.select(): # 列出數(shù)據(jù)庫中的所有人
print(person.name)
dog_list = Pet.select().where(Pet.animal_type == 'dog') # 列出所有狗及其主人的名字
for dog in dog_list:
print(dog.name, dog.owner.name)
# (2)獲取wangyifan擁有的所有寵物
for pet in Pet.select().join(Person).where(Person.name == 'wangyifan'):
print(pet.name)
# (3)排序 order_by()
for pet in Pet.select().where(Pet.owner == old_wang).order_by(Pet.name): # 列出寵物按姓名排序
print(pet.name)
for person in Person.select().order_by(Person.birthday.desc()): # 列出所有人,從年輕到年長(zhǎng)
print(person.name, person.birthday)
#(4) 組合過濾器表達(dá)式
d1995 = date(1995, 3, 1)
d1996 = date(1996, 1, 1)
# 生日小于1995大于1996 兩個(gè)日期直接可以用Person.birthday.between(d1940, d1960)
person_list = (Person.select().where((Person.birthday < d1995) | (Person.birthday > d1996)))
for person in person_list:
print(person.name, person.birthday)
# (5)聚合和預(yù)取
for person in Person.select():
print(person.name, person.pets.count(), 'pets')
'''4.數(shù)據(jù)庫'''
# 關(guān)閉連接
db.close()
# 使用現(xiàn)有數(shù)據(jù)庫,如已有數(shù)據(jù)庫,則可以使用模型生成器pwiz自動(dòng)生成peewee模型 。
# 例如,有一個(gè)名為charles_blog的postgresql數(shù)據(jù)庫 ,則可以執(zhí)行如下命令
# python -m pwiz -e postgresql charles_blog > blog_model.py
4.pymysql
安裝
pip install PyMySQL
案例
# -*- coding:utf-8 -*-
import pymysql
'''1.數(shù)據(jù)庫查詢操作'''
db = pymysql.connect("localhost","root","root","hd_20190424") # 地址,用戶名,密碼,數(shù)據(jù)庫名
# 使用cursor()方法創(chuàng)建一個(gè)游標(biāo)對(duì)象 cursor
cursor = db.cursor()
# 使用execute()方法執(zhí)行sql語句
cursor.execute("select version()")
# 使用fetchone()方法獲取單條數(shù)據(jù)
data = cursor.fetchone()
print("database version:%s" % data)
# 關(guān)閉數(shù)據(jù)庫連接
db.close()
'''2.數(shù)據(jù)庫插入操作'''
import pymysql
# 打開數(shù)據(jù)庫連接
db = pymysql.connect("localhost","root","root","hd_20190424")
# 使用cursor()方法獲取操作游標(biāo)
cursor = db.cursor()
# SQL 插入語句
sql = """INSERT INTO hd_20190424(username,age)VALUES ('wangyifan', 25)"""
try:
# 執(zhí)行sql語句
cursor.execute(sql)
# 提交到數(shù)據(jù)庫執(zhí)行
db.commit()
except:
# 如果發(fā)生錯(cuò)誤則回滾
db.rollback()
# 關(guān)閉數(shù)據(jù)庫連接
db.close()
5.PyYAML
安裝
pip install pyyaml
案例
# -*- coding:utf-8 -*-
import yaml
# 加載YAML
yaml_obj = yaml.load("""- Hesperiida
- Papilionidae
- Apatelodidae
- Epiplemidae""")
print (yaml_obj)
# PyYAML允許您構(gòu)造任何類型的Python對(duì)象。
yaml_obj2 = yaml.load("""
none:[~,null]
bool:[True,False,on,off]
int:33
float:3.1415926
list:[wangyifan,1,'ddd']
dic:[name:wang,age:25]
""")
print(yaml_obj2)
# 傾倒YAML
print yaml.dump({'name': 'Silenthand Olleander', 'race': 'Human', 'traits': ['ONE_HAND', 'ONE_EYE']})
#打開并顯示yaml文件內(nèi)容
import yaml
f=open('yaml_data.ini')
data=yaml.load(f)
print data,'=========data'
#將Python對(duì)象寫入yaml文件
f=open('data.yaml','w')
data={
'name': 'Silenthand Olleander',
'race': 'Human',
'traits': ['ONE_HAND', 'ONE_EYE']
}
yaml.dump(data,f)
6.* requests
安裝
pip install requests
案例
# -*- coding:utf-8 -*-
import requests
'''1.get請(qǐng)求'''
# 請(qǐng)求
r = requests.get('https://www.baidu.com')
# 傳參
params_data = {'wd':'wangyifan'}
r = requests.get('https://www.baidu.com', params=params_data)
print(r.url) # 訪問地址
print(r.text) # 獲取網(wǎng)頁文本 返回的是Unicode型的數(shù)據(jù) Unicode
print(r.content) #獲取網(wǎng)頁文本 返回的是bytes型也就是二進(jìn)制的數(shù)據(jù)。 str
# print(r.json()) # 如果獲取的是json數(shù)據(jù)的話
print(r.status_code) # 狀態(tài)
r = requests.get('https://www.baidu.com',stream=True)
print(r.raw) # 返回原始socket respons,需要加參數(shù)stream=True
print(r.raw.read(10),'====')
print(r.cookies,'===')
'''2.POST請(qǐng)求'''
# 請(qǐng)求
r = requests.post('http://httpbin.org/post', data = {'key':'value'})
# 參數(shù)
data_msg = {'key1': 'value1', 'key2': 'value2'}
r = requests.post("http://httpbin.org/post", data=data_msg)
print(r.text)
print(r.cookies)
# 文件傳遞
url = 'http://httpbin.org/post'
files = {'file': open('report.xls', 'rb')}
r = requests.post(url, files=files)
# session
# session對(duì)象能夠幫我們跨請(qǐng)求保持某些參數(shù),也會(huì)在同一個(gè)session實(shí)例發(fā)出的所有請(qǐng)求之間保持cookies。
s = requests.Session() # 創(chuàng)建一個(gè)session對(duì)象
s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
r = s.get('http://httpbin.org/cookies')
print(r.text,'==========')
7.* PyStaticConfiguration
安裝
# -*- coding:utf-8 -*-
import staticconf
'''
1.staticconf是一個(gè)庫,用于從許多異構(gòu)格式加載配置值并讀取這些值。
該過程分為兩個(gè)階段(配置加載和讀取配置值)。
'''
# 案例,給定兩個(gè)文件
# application.yaml
'''
pid : /var/run/app1.pid
storage_paths :
- / mnt / storage
- / mnt / nfs
min_date : 2014-12-12
groups :
users :
- userone
- usertwo
admins :
- admin
'''
# overrides.yaml
'''
max_files: 10
groups:
users:
- customuser
'''
# 加載配置
import staticconf
app_config = 'application.yaml'
app_custom = 'overrides.yaml'
staticconf.YamlConfiguration(app_config)
staticconf.YamlConfiguration(app_custom, optional=True) # 覆蓋app_config中的配置
# 讀取配置
import staticconf
pid = staticconf.read_string('pid')
storage_paths = staticconf.read_list_of_string('storage_paths')
users = staticconf.read_list_of_string('groups.users')
admins = staticconf.read_list_of_string('groups.admins')
min_date = staticconf.read_date('min_date')
print(pid)
print(storage_paths)
print(users)
print(admins)
print(min_date)
'''2.readers'''
# 例子 read an int
import staticconf
config = staticconf.NamespaceReaders('bling')
max_cycles = config.read_int('max_cycles')
ratio = config.read_float('ratio')
'''3.Schemas'''
from staticconf import schema
class SomethingUsefulSchema(schema.Schema):
namespace = 'useful_namespace'
config_path = 'useful'
max_value = schema.int(default=100)
ratio = schema.float()
msg = schema.any(config_key='msg_string', default="Welcome")
config = SomethingUsefulSchema()
print config.msg
'''4.getters'''
import staticconf
# Returns a ValueProxy which can be used just like an int
max_cycles = staticconf.get_int('max_cycles')
print "Half of max_cycles", max_cycles / 2
# 對(duì)象從命名空間使用NamespaceGetters對(duì)象
config = staticconf.NamespaceGetters('special')
ratio = config.get_float('ratio')
案例
8.* jinja2
安裝
pip install jinja2
案例
# -*- coding: utf-8 -*-
from jinja2 import Template
'''1.基本API用法'''
template = Template('hello {{ name }}')
print template.render(name='wangyifan')
# 使用包加載器來加載文檔的最簡(jiǎn)單的方式如下:
from jinja2 import PackageLoader, Environment
env = Environment(loader=PackageLoader('python_project', 'templates')) # 創(chuàng)建一個(gè)包加載器對(duì)象
template = env.get_template('bast.html') # 獲取一個(gè)模板文件
template.render(name='daxin', age=18) # 渲染
'''2.jinja2基本語法 使用與Django DTL模板語法類似'''
# 1.控制結(jié)構(gòu) {% %}
# 2.變量取值 {{}}
# 3.注釋{# #}
{# 這是注釋 #}
{% for person in person_list %}
<p>name is {{ person.name }}</p>
{% endfor %}
'''3.繼承'''
{ % extend"base.html" %} # 繼承base.html文件
{ % blocktitle %} Dachenzi{ % endblock %} # 定制title部分的內(nèi)容
{ % blockhead %}{{super()}} # 用于獲取原有的信息
< styletype = 'text/css' >.important{color: # FFFFFF }< / style >
{ % endblock %}
'''4.過濾器'''
# safe 渲染時(shí)值不轉(zhuǎn)義
# capitialize 把值的首字母轉(zhuǎn)換成大寫,其他子母轉(zhuǎn)換為小寫
# lower 把值轉(zhuǎn)換成小寫形式
# upper 把值轉(zhuǎn)換成大寫形式
# title 把值中每個(gè)單詞的首字母都轉(zhuǎn)換成大寫
# trim 把值的首尾空格去掉
# striptags 渲染之前把值中所有的HTML標(biāo)簽都刪掉
# join 拼接多個(gè)值為字符串
# replace 替換字符串的值
# round 默認(rèn)對(duì)數(shù)字進(jìn)行四舍五入,也可以用參數(shù)進(jìn)行控制
# int 把值轉(zhuǎn)換成整型
# 使用方式
# {{ 'abc' | upper }} >>> ABC
9.* blinker
Blinker為Python對(duì)象提供快速簡(jiǎn)單的對(duì)象到對(duì)象和廣播信令。
Blinker的核心很小但提供了強(qiáng)大的功能:
- 命名信號(hào)的全球注冊(cè)表
- 匿名信號(hào)
- 自定義名稱注冊(cè)表
- 永久或臨時(shí)連接的接收器
- 通過弱引用自動(dòng)斷開接收器
- 發(fā)送任意數(shù)據(jù)有效載荷
- 從信號(hào)接收器收集返回值
- 線程安全
安裝
pip install blinker
案例
# -*-coding:utf-8 -*-
from blinker import signal
'''1.創(chuàng)建信號(hào)'''
# 信號(hào)通過signal()方法進(jìn)行創(chuàng)建
sig = signal("sig")
sig is signal("sig")
# 每次調(diào)用signal('name')都會(huì)返回同一個(gè)信號(hào)對(duì)象。因此這里signal()方法使用了單例模式。
'''2.訂閱信號(hào)'''
# 使用Signal.connect()方法注冊(cè)一個(gè)函數(shù),每當(dāng)觸發(fā)信號(hào)的時(shí)候,就會(huì)調(diào)用該函數(shù)。
# 該函數(shù)以觸發(fā)信號(hào)的對(duì)象作為參數(shù),這個(gè)函數(shù)其實(shí)就是信號(hào)訂閱者。
def subscriber(sender):
print('got a signal by %r' % sender)
ready = signal('ready')
print(ready.connect(subscriber))
'''3.觸發(fā)信號(hào)'''
# 使用Signal.send()方法通知信號(hào)訂閱者。
#下面定義類Processor,在它的go()方法中觸發(fā)前面聲明的ready信號(hào),send()方法以self為參數(shù),
# 也就是說Processor的實(shí)例是信號(hào)的發(fā)送者。
class Processor:
def __init__(self,name):
self.name = name
def go(self):
ready = signal('ready')
ready.send(self)
print("Processing.")
complete = signal('complete')
complete.send(self)
def __str__(self):
return '<Processor %s>' % self.name
def __repr__(self):
return '<Processor %s>' % self.name
processor_a = Processor('a')
processor_a.go()
10.pytest
該pytest框架可以輕松編寫小型測(cè)試,然后進(jìn)行擴(kuò)展以支持應(yīng)用程序和庫的復(fù)雜功能測(cè)試。
安裝
pip install -U pytest
pytest --version # 驗(yàn)證安裝是否成功
案例
pytest_tools.py
這里我們定義了一個(gè)被測(cè)試函數(shù)func,該函數(shù)將傳遞進(jìn)來的參數(shù)加1后返回。我們還定義了一個(gè)測(cè)試函數(shù)test_func用來對(duì)func進(jìn)行測(cè)試。test_func中我們使用基本的斷言語句assert來對(duì)結(jié)果進(jìn)行驗(yàn)證。
# -*- coding:utf-8 -*-
def func(x):
return x + 1
def test_answer():
assert func(3) == 5
在命令行執(zhí)行 pytest pytest_tools.py

執(zhí)行測(cè)試的時(shí)候,我們只需要在測(cè)試文件test_sample所在的目錄下,運(yùn)行py.test即可。pytest會(huì)在當(dāng)前的目錄下,尋找以test開頭的文件(即測(cè)試文件),找到測(cè)試文件之后,進(jìn)入到測(cè)試文件中尋找test_開頭的測(cè)試函數(shù)并執(zhí)行。
通過上面的測(cè)試輸出,我們可以看到該測(cè)試過程中,一個(gè)收集到了一個(gè)測(cè)試函數(shù),測(cè)試結(jié)果是失敗的(標(biāo)記為F),并且在FAILURES部分輸出了詳細(xì)的錯(cuò)誤信息,幫助我們分析測(cè)試原因,我們可以看到"assert func(3) == 5"這條語句出錯(cuò)了,錯(cuò)誤的原因是func(3)=4,然后我們斷言func(3) 等于 5。