deffunc_write(q): for data in ["A", "B"]: q.put(data) deffunc_read(q): whileTrue: data = q.get(True) print(data)
q = Queue() # can be modify by multi processes, not copy pw = Process(target=func_write, args=(q,)) pr = Process(target=func_read, args=(q,)) pw.start() pr.start() pw.join() # main process wait for pw finishing pr.terminate() # kill endless loop process
deflogin(): if (request.args.get('username', type=str) == "admin" and request.args.get('password', type=str) == "pwd"): return'<h3>Hello, admin!</h3>' return'<h3>Bad username or password.</h3>' # bind func using `add_url_rule` instead of decorator # url, endpoint (for url_for(), = None is ok), func, methods=['POST','GET'] default is GET only app.add_url_rule("/api/login", "login", login)
@app.route('/api/json', methods=['POST']) defjson2html(): print("json api post content type:", request.content_type) if request.get_json() isnotNone: json_data = request.get_json() html = "<p>content type is application/json</p>" else: html = "<p>content type is text/html</p>" json_data = json.loads(request.get_data(as_text=True)) for key in json_data: html += f"<p>{key}: {json_data[key]}</p>" return html
import io import base64 from PIL import Image @app.route('/api/image_base64', methods=['POST']) defrotate_image(): print("image api post content type:", request.content_type) data = {"successed": False} if request.method == 'POST'and request.files.get('image'): image = request.files["image"].read() image = Image.open(io.BytesIO(image)).convert("RGB") image = image.rotate(90)
使用 urllib.request.urlopen(url) 可直接發送一個 GET 請求到指定 url。返回無論是 文本、HTML、JSON、base64 都作為文本讀入。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
from urllib import request
with request.urlopen('http://127.0.0.1:5000/') as f: data = f.read() # data = json.loads(data) # if response is json data print('Status:', f.status, f.reason) # f.getcode()=f.status for k, v in f.getheaders(): print('%s: %s' % (k, v)) print('Data:', data.decode('utf-8'))
req = request.Request('http://www.douban.com/') # method='GET' req.add_header('User-Agent', 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Mobile/15E148 Safari/604.1') request.urlopen(req)
POST 請求需要用到 urlopen 的 data= 參數。默認 Content-Type: application/x-www-form-urlencoded (form)。另一種格式是 json,需要先構造一個 Request(需要 header)。含有 data 默認 method 為 POST?
# post form login_data = parse.urlencode([ ('username', 'admin'), ('password', 'pwd'), ]) # username=admin&password=password form
with request.urlopen('http://127.0.0.1:5000/signin', data=login_data.encode('utf-8')) as f: data = f.read() print('Status:', f.status, f.reason) for k, v in f.getheaders(): print('%s: %s' % (k, v)) print('Data:', data.decode('utf-8'))
# post json import json login_data = json.dumps({ 'username': 'admin', 'password': 'pwd', }, ensure_ascii=False) login_data = bytes(login_data, 'utf-8') # login_data.encode('utf-8') headers = {'Content-Type':'application/json'} req = request.Request("http://127.0.0.1:5000/api/json", headers=headers, data=login_data, method='POST') with request.urlopen(req) as f: data = f.read() print('Data:', data.decode('utf-8'))
# get with headers r = requests.get( 'https://www.douban.com/', headers={'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Mobile/15E148 Safari/604.1'} ) # headers 可省略 r.status_code, r.headers # headers of response r.text # text '<h3>Hello, admin!</h3>' r.content # show binary of any pure return b'<h3>Hello, admin!</h3>'
# get binary image with 'Content-Type': 'image/jpeg' r = requests.get("https://i0.hdslb.com/bfs/archive/.jpg") image = Image.open(BytesIO(r.content))
# get with url params r = requests.get('http://127.0.0.1:5000/api/login', params={'username': 'admin', 'password': 'pwd'}) r.url # 'http://127.0.0.1:5000/api/login?username=admin&password=pwd'
# get json object r = requests.get('https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20%3D%202151330&format=json') r = requests.get('http://127.0.0.1:5000/hello/39/admin') r.json() # dict {'id': 39, 'name': 'admin'}, = json.loads(r.content.decode("utf-8"))
# post form (application/x-www-form-urlencoded) r = requests.post('http://127.0.0.1:5000/signin', data={'username': 'admin', 'password': 'pwd'})
一個 Data Class 來定時拉取、處理、更新數據,將結果調用 HTTP Class 的更新函數保存到其 .data 中。HTTP Class 更新和返回數據的方法需要有線程鎖,保證這兩個函數在兩個 Class(處於兩個線程)中不會同時調用(改變和獲取數據不同時發生)。由於兩個 Class 都需要 serve forever,且更新的頻率會遠低於查詢的,為了不互相阻塞需要在兩個線程中。
http_server = RunSearch() data = Data(http_server) data.start() # won't stop here by while loop, this thread won't stop http_server.app.run("0.0.0.0", 5000) # Running on http://114.224.62.114:5000/ # ctrl+c to stop Flask, main thread end -> daemon child thread end # daemon=False ctrl+c twice