python 項目生成requirements.txt等文件
pip install pipreqs
# 項目目錄執(zhí)行
pipreqs ./
python call 方法
Call self as a function
主要實現(xiàn)的是將類的對象當作函數(shù)直接調(diào)用
#
class type(object):
def __call__(self, *args, **kwargs): # real signature unknown
""" Call self as a function. """
pass
call示例
def __call__(self, environ, start_response):
self.proxied = False
script_name = environ.get('HTTP_X_SCRIPT_NAME', '')
if script_name:
self.proxied = True
environ['SCRIPT_NAME'] = script_name
path_info = environ.get('PATH_INFO', '')
if path_info and path_info.startswith(script_name):
environ['PATH_INFO'] = path_info[len(script_name):]
scheme = environ.get('HTTP_X_SCHEME', '')
if scheme:
environ['wsgi.url_scheme'] = scheme
servr = environ.get('HTTP_X_FORWARDED_HOST', '')
if servr:
environ['HTTP_HOST'] = servr
self.proxied = True
return self.app(environ, start_response)
Django、Tornado、Flask比較
使用flask好久,感覺flask還是好用些。
Django是Python 中最全能的 web 開發(fā)框架,走大而全的方向。它最出名的是其全自動化的管理后臺:只需要使用起ORM,做簡單的對象定義,它就能自動生成數(shù)據(jù)庫結(jié)構(gòu)、以及全功能的管理后臺。不過Django提供的方便,也意味著Django內(nèi)置的ORM跟框架內(nèi)的其他模塊耦合程度高,深度綁定了該框架,應(yīng)用程序必須使用Django內(nèi)置的ORM,否則就不能享受到框架內(nèi)提供的種種基于其ORM的優(yōu)秀特性。
Tornado全稱Tornado Web Server,是一個用Python語言寫成的Web服務(wù)器兼Web應(yīng)用框架。Tornado走的是少而精的方向,注重的是性能優(yōu)越,它最出名的是異步非阻塞的服務(wù)器方式。(Tornado框架和服務(wù)器一起組成一個WSGI的全棧替代品。單獨在WSGI容器中使用tornado web框架或者tornaod http服務(wù)器,有一定的局限性,為了最大化的利用tornado的性能,推薦同時使用tornaod的web框架和HTTP服務(wù)器。)
Flask是一個使用 Python 編寫的輕量級 Web 應(yīng)用框架,也被稱為 “microframework”,語法簡單,部署很方便,整個框架自帶了路徑映射、模板引擎(Jinja2)、簡單的數(shù)據(jù)庫訪問等web框架組件,支持WSGI協(xié)議(采用 Werkzeug)。Flask使用 BSD 授權(quán)。 Flask使用簡單的核心,用 extension 增加其他功能,雖然沒有默認使用的數(shù)據(jù)庫、窗體驗證工具,然而Flask保留了擴增的彈性,可以用Flask-extension加入ORM、窗體驗證工具、文件上傳、各種開放式身份驗證技術(shù)這些功能。
從性能上看Tornado 比Django、Flask等主流 Web 服務(wù)器框架相比有著明顯的區(qū)別:它是非阻塞式服務(wù)器,速度相當快。然而 Tornado 相比 Django 和Flask屬于較為原始的框架,插件少,許多內(nèi)容需要自己去處理。而Flask插件多,文檔非常專業(yè),有專門的公司團隊維護,對于快速開發(fā)很有效率。由于WSGI協(xié)議的存在,可以結(jié)合 Tornado 的服務(wù)器異步特性、并發(fā)處理能力和Flask的文檔和擴展能力為一體。雖然像Django,F(xiàn)lask框架都有自己實現(xiàn)的簡單的WSGI服務(wù)器,但一般用于服務(wù)器調(diào)試,生產(chǎn)環(huán)境下建議用其他WSGI服務(wù)器,比如Nginx+uwsgi+Django方式。
參考
python-tornado簡單使用
Python的web架構(gòu)之Tornado+Flask
python 裝飾器
裝飾器能夠在那個函數(shù)執(zhí)行前或者執(zhí)行后分別運行一些代碼,使得可以再裝飾器里面訪問并修改原函數(shù)的參數(shù)以及返回值,以實現(xiàn)約束定義、調(diào)試程序、注冊函數(shù)等目標。裝飾器一般返回一個包裝器(wrapper),而functools.wraps就是裝飾包裝器的裝飾器。
自己創(chuàng)建一個裝飾器
def a_new_decorator(a_func):
def wrapTheFunction():
print("I am doing some boring work before executing a_func()")
a_func()
print("I am doing some boring work after executing a_func()")
return wrapTheFunction
def a_function_requiring_decoration():
print("I am the function which needs some decoration to remove my foul smell")
a_function_requiring_decoration()
#outputs: "I am the function which needs some decoration to remove my foul smell"
a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
#now a_function_requiring_decoration is wrapped by wrapTheFunction()
a_function_requiring_decoration()
#outputs:I am doing some boring work before executing a_func()
# I am the function which needs some decoration to remove my foul smell
# I am doing some boring work after executing a_func()
from functools import wraps
def a_new_decorator(a_func):
@wraps(a_func)
def wrapTheFunction():
print("I am doing some boring work before executing a_func()")
a_func()
print("I am doing some boring work after executing a_func()")
return wrapTheFunction
@a_new_decorator
def a_function_requiring_decoration():
"""Hey you! Decorate me!"""
print("I am the function which needs some decoration to "
"remove my foul smell")
a_function_requiring_decoration()
a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
print(a_function_requiring_decoration.__name__)
輸出結(jié)果為
I am doing some boring work before executing a_func()
I am the function which needs some decoration to remove my foul smell
I am doing some boring work after executing a_func()
a_function_requiring_decoration
python 修飾符@
修飾符@的作用是為現(xiàn)有函數(shù)增加額外的功能,常用于插入日志、性能測試、事務(wù)處理等等。
創(chuàng)建函數(shù)修飾符的規(guī)則:
(1)修飾符是一個函數(shù)
(2)修飾符取被修飾函數(shù)為參數(shù)
(3)修飾符返回一個新函數(shù)
(4)修飾符維護被維護函數(shù)的簽名
修飾符@是一個函數(shù)
def log(func):
def wrapper():
print('log開始 ...')
func()
print('log結(jié)束 ...')
return wrapper
@log
def run_func():
print('run_func ..')
run_func()
#log開始 ...
#run_func ..
#log結(jié)束 ...
修飾符@維護被維護函數(shù)的簽名
使用functools模塊提供的修改函數(shù)屬性的方法wraps
from functools import wraps
def log(func):
@wraps(func)
def wrapper():
print('log開始 ...')
func()
print('log結(jié)束 ...')
return wrapper
@log
def test1():
print('test1 ..')
def test2():
print('test2 ..')
print(test1.__name__)
print(test2.__name__)
#test1
#test2
被修飾函數(shù)帶參數(shù)
from functools import wraps
def log(func):
@wraps(func)
def wrapper(*args,**kwargs):
print('log開始 ...',func.__name__)
ret = func(*args,**kwargs)
print('log結(jié)束 ...')
return ret
return wrapper
@log
def test1(s):
print('test1 ..', s)
return s
@log
def test2(s1, s2):
print('test2 ..', s1, s2)
return s1 + s2
test1('a')
test2('a','bc')
參考
python 打開文件
f = file(name[, mode[, buffering]])
入口參數(shù): name 文件名
mode 選項,字符串
buffering 是否緩沖 (0=不緩沖,1=緩沖, >1的int數(shù)=緩沖區(qū)大小)
返回值 : 文件對象
mode 選項:
"r" 以讀方式打開,只能讀文件 , 如果文件不存在,會發(fā)生異常
"w" 以寫方式打開,只能寫文件, 如果文件不存在,創(chuàng)建該文件
如果文件已存在,先清空,再打開文件
"rb" 以二進制讀方式打開,只能讀文件 , 如果文件不存在,會發(fā)生異常
"wb" 以二進制寫方式打開,只能寫文件, 如果文件不存在,創(chuàng)建該文件
如果文件已存在,先清空,再打開文件
"rt" 以文本讀方式打開,只能讀文件 , 如果文件不存在,會發(fā)生異常
"wt" 以文本寫方式打開,只能寫文件, 如果文件不存在,創(chuàng)建該文件
如果文件已存在,先清空,再打開文件
"rb+" 以二進制讀方式打開,可以讀、寫文件 , 如果文件不存在,會發(fā)生異常
"wb+" 以二進制寫方式打開,可以讀、寫文件, 如果文件不存在,創(chuàng)建該文件
如果文件已存在,先清空,再打開文件
python3.8使用flask_wtf時產(chǎn)生的cannot import name 'url_encode'問題
werkzeug 版本過高,導(dǎo)致問題出現(xiàn);安裝werkzeug的低版本即可解決問題
pip install werkzeug==0.16.0
flask 渲染html
from flask import render_template
@app.route('/user/')
def user():
return render_template('user.html')
if __name__ == '__main__':
app.run(debug=True)
# user.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>這是用戶中心</title>
<h1>這是用戶中心! </h1>
</head>
<body>
</body>
</html>
python 3.7 async=True, get_object=False, no_input=False):
pip install pyspider
pyspider
? Containers Pyspider
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.8/bin/Pyspider", line 5, in <module>
from pyspider.run import main
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyspider/run.py", line 231
async=True, get_object=False, no_input=False):
^
原因是python3.7中async已經(jīng)變成了關(guān)鍵字。因此出現(xiàn)這個錯誤。
修改方式是手動替換一下
下面位置的async改為mark_async
/usr/local/lib/python3.7/site-packages/pyspider/run.py 的231行、245行(兩個)、365行
/usr/local/lib/python3.7/site-packages/pyspider/webui/app.py 的95行
/usr/local/lib/python3.7/site-packages/pyspider/fetcher/tornado_fetcher.py 的81行、89行(兩個)、95行、117行
~ pyspider
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.8/bin/pyspider", line 8, in <module>
sys.exit(main())
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyspider/run.py", line 754, in main
cli()
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/click/core.py", line 829, in __call__
return self.main(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/click/core.py", line 782, in main
rv = self.invoke(ctx)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/click/core.py", line 1236, in invoke
return Command.invoke(self, ctx)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/click/core.py", line 1066, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/click/core.py", line 610, in invoke
return callback(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/click/decorators.py", line 21, in new_func
return f(get_current_context(), *args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyspider/run.py", line 165, in cli
ctx.invoke(all)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/click/core.py", line 610, in invoke
return callback(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/click/decorators.py", line 21, in new_func
return f(get_current_context(), *args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyspider/run.py", line 467, in all
threads.append(run_in(ctx.invoke, phantomjs, **phantomjs_config))
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyspider/libs/utils.py", line 68, in run_in_subprocess
thread.start()
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/process.py", line 121, in start
self._popen = self._Popen(self)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/context.py", line 224, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/context.py", line 284, in _Popen
return Popen(process_obj)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/popen_spawn_posix.py", line 32, in __init__
super().__init__(process_obj)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/popen_fork.py", line 19, in __init__
self._launch(process_obj)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/popen_spawn_posix.py", line 47, in _launch
reduction.dump(process_obj, fp)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/reduction.py", line 60, in dump
ForkingPickler(file, protocol).dump(obj)
_pickle.PicklingError: Can't pickle <function cli at 0x7fe59a5735e0>: it's not the same object as pyspider.run.cli
解決方法:使用pipenv
參考
https://www.cnblogs.com/jiguanghover/p/11364513.html
python 多線程實現(xiàn)同步的四種方式
https://www.cnblogs.com/zhumengke/articles/10825242.html
Python raise
http://c.biancheng.net/view/2360.html
Python functools.partial
partial adj. 局部的;偏愛的;不公平的
Python 提供了一個 functools 的模塊,該模塊為高階函數(shù)提供支持,partial 就是其中的一個函數(shù)
def add(x, y):
return x + y
add(3, y=2)
add(4, y=2)
add(5, y=2)
def plus(x, y=2):
return add(x, y)
plus(3)
plus(4)
plus(5)
from functools import partial
plus = partial(add, y=2)
partial 接收函數(shù) add 作為參數(shù),固定 add 的參數(shù) y=2,并返回一個新的函數(shù)給 plus。簡單而言,partial 函數(shù)的功能就是:把一個函數(shù)的某些參數(shù)給固定住,返回一個新的函數(shù)。
參考
端口轉(zhuǎn)發(fā)
server{
listen 80;
server_name tomcat.shaochenfeng.com;
index index.php index.html index.htm;
location / {
proxy_pass http://127.0.0.1:8080; # 轉(zhuǎn)發(fā)規(guī)則
proxy_set_header Host $proxy_host; # 修改轉(zhuǎn)發(fā)請求頭,讓8080端口的應(yīng)用可以受到真實的請求
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}