2017年6月19日 星期一

MicroPython on ESP8266 (十二) : urequests 模組測試

做完 urllib.urequest 模組的測試後, 我又在 "精通 Python (Oreilly 出版)" 這本書的第九章後面看到作者介紹第三方函式庫 requests, 與 urllib.urequest 模組一樣, 可以很方便地處理 HTTP 請求. 在 CPython 可以利用下列指令安裝 requests :

 C:\Users\Tony>pip3 install requests

MicroPython 已經實作了 requests 的子集, 稱為 urequests (不可用 requests), 直接匯入即可使用 :

import urequests

此模組所實作的方法可用 dir() 顯示 :

>>> import urequests
>>> dir(urequests)
['Response', 'patch', '__name__', 'request', 'delete', 'get', 'head', 'post', 'put', 'usocket']

可見 HTTP 的主要方法 GET, POST, HEAD, PUT, DELETE 等都有支援.

雖然 urequests 並非完全實作 requests, 用法仍可參考官網文件 :

Requests: HTTP for Humans

下列文件則有許多範例 :

HTTPS POST using urequests.py and Guru Mediation Error
Python爬虫利器一之Requests库的用法
# Wemos D1 mini User's Guide (PDF) (搜尋 HTTP Request)

 本系列測試紀錄前十一篇參考 :

MicroPython on ESP8266 (二) : 數值型別測試
MicroPython on ESP8266 (三) : 序列型別測試
MicroPython on ESP8266 (四) : 字典與集合型別測試
MicroPython on ESP8266 (五) : WiFi 連線與 WebREPL 測試
MicroPython on ESP8266 (六) : 檔案系統測試
MicroPython on ESP8266 (七) : 時間日期測試
MicroPython on ESP8266 (八) : GPIO 測試
MicroPython on ESP8266 (九) : PIR 紅外線移動偵測
MicroPython on ESP8266 (十) : socket 模組測試
# MicroPython on ESP8266 (十一) : urllib.urequest 模組測試

MicroPython 文件參考 :

MicroPython tutorial for ESP8266  (官方教學)
http://docs.micropython.org/en/latest/micropython-esp8266.pdf
http://docs.micropython.org/en/latest/pyboard/library/usocket.html#class-socket
http://docs.micropython.org/en/v1.8.7/esp8266/library/usocket.html#module-usocket
https://gist.github.com/xyb/9a4c8d7fba92e6e3761a (驅動程式)

使用 urequests 模組只要使用 import 匯入, 就可以用 get() 或 post() 等方法提出 GET 或 POST 方法了, 其傳回值是一個 Response 物件, 回應內容就放在其 text 屬性中, 例如 :

>>> import urequests
>>> r=urequests.get("http://micropython.org/ks/test.html")
>>> r
<Response object at 3fff21e0>
>>> type(r)
<class 'Response'>      #get() 方法傳回 Response 物件
>>> type(r.text)
<class 'str'>                 #text 屬性存放的是 str 類型 (字串, utf-8 編碼)
>>> r.text              #顯示 text 內容
'<!DOCTYPE html>\n<html lang="en">\n    <head>\n        <title>Test</title>\n    </head>\n    <body>\n        <h1>Test</h1>\n        It\'s working if you can read this!\n    </body>\n</html>\n'
>>> print(r.text)    #用 print() 格式化輸出
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Test</title>
    </head>
    <body>
        <h1>Test</h1>
        It's working if you can read this!
    </body>
</html>

>>>

這比直接處理 HTTP 協定要簡單省事多了.

除了直接用 text 屬性來讀取回應內容外, 也可以用 Response 物件的 content 屬性, 此屬性存放的是從 socket 讀取的原始二進位回應資料 (bytes 型態) :

>>> type(r.content)  
<class 'bytes'>                   #content 屬性存的是 byte 串流 (已轉為 ASCII)
>>> r.content              #讀取二進位回應資料
b'<!DOCTYPE html>\n<html lang="en">\n    <head>\n        <title>Test</title>\n    </head>\n    <body>\n        <h1>Test</h1>\n        It\'s working if you can read this!\n    </body>\n</html>\n'
>>> print(r.content)     #byte 資料用 print() 不會格式化
b'<!DOCTYPE html>\n<html lang="en">\n    <head>\n        <title>Test</title>\n    </head>\n    <body>\n        <h1>Test</h1>\n        It\'s working if you can read this!\n    </body>\n</html>\n'

另外, Response 物件還有一個存放 socket 物件的 raw 屬性, 也可以透過此物件的 read() 方法讀取回應資料 (也是 bytes 類型) :

>>> r=urequests.get("http://micropython.org/ks/test.html")
>>> type(r.raw)
<class 'socket'>                    #raw 存放的是 socket 物件
>>> r.raw
<socket state=3 timeout=-1 incoming=3fff9ba8 off=0>
>>> r.raw.read()             #讀取全部回應資料 (=r.content)
b'<!DOCTYPE html>\n<html lang="en">\n    <head>\n        <title>Test</title>\n    </head>\n    <body>\n        <h1>Test</h1>\n        It\'s working if you can read this!\n    </body>\n</html>\n'
>>> r.raw.read(20)         #read() 已讀完全部緩衝區, 故為空
b''
>>> r=urequests.get("http://micropython.org/ks/test.html")   #重新 get
>>> r.raw.read(20)         #讀取前面 20 個字元
b'<!DOCTYPE html>\n<htm'
>>>

Response 物件的 status_code 屬性儲存回應狀態, 正常是 200; 而 encoding 屬性存放編碼格式 :

>>> r.status_code
200  
>>> r.encoding
'utf-8'

但是 MicroPython 的 urequests 模組的 Response 物件沒有實作 url 與 headers  等屬性 :

>>> r.url                                   #顯示請求之 url
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Response' object has no attribute 'url'
>>> r.headers                           #顯示全部標頭
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Response' object has no attribute 'headers'
>>> r.headers['content-type']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Response' object has no attribute 'headers'
>>> r.cookies
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>

AttributeError: 'Response' object has no attribute 'cookies'

而在 CPython 中執行結果如下 :

Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> r=requests.get("http://micropython.org/ks/test.html")
>>> r.url                                     #顯示請求之 url
'http://micropython.org/ks/test.html'
>>> r.headers                             #顯示全部標頭
{'Server': 'nginx/1.8.1', 'Date': 'Sun, 18 Jun 2017 23:19:41 GMT', 'Content-Type': 'text/html', 'Last-Modified': 'Tue, 03 Dec 2013 00:16:26 GMT', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding', 'ETag': 'W/"529d22da-b4"', 'Content-Encoding': 'gzip'}
>>> r.headers['content-type']    #顯示指定標頭
'text/html'
>>>

雖然 MicroPython 未實作 headers 屬性, 但可以利用 httpbin.org 所提供的 get/post 方法取得, 它會把請求標頭放在回應訊息內容中以 JSON 格式傳回來, 這就要用到 Response 物件的 json() 方法來處理回應內容了.

Response 物件的 json() 方法可將回應之 json 字串轉成 dict 物件, 但是回應內容必須是例如 '{"a":"1", "b":2"}' 的 JSON 格式字串, 否則會出現語法錯誤, 例如 MicroPython 測試網頁回應內容是 HTML 檔案, 呼叫 json() 方法就會出錯 :

>>> r=urequests.get("http://micropython.org/ks/test.html")
>>> r.json()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "urequests.py", line 30, in json
ValueError: syntax error in JSON

但如果使用 httpbin.org 的 GET 測試網頁 http://httpbin.org/get , 其回應內容為 JSON 格式, 這樣呼叫 Response 物件的 json() 方法就不會出現錯誤訊息, 而是將 JSON 字串轉成 dict 物件傳回. 如果用瀏覽器連線 http://httpbin.org/get 會得到如下回應 :

{
  "args": {}, 
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 
    "Accept-Encoding": "gzip, deflate, sdch", 
    "Accept-Language": "zh-TW,zh;q=0.8,en-US;q=0.6,en;q=0.4", 
    "Connection": "close", 
    "Cookie": "_gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1; _gauges_unique_day=1", 
    "Host": "httpbin.org", 
    "Upgrade-Insecure-Requests": "1", 
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 OPR/45.0.2552.898"
  }, 
  "origin": "12.174.116.121", 
  "url": "http://httpbin.org/get"
}

httpbin.org 伺服器會將請求訊息的標頭組成 JSON 字串後放在回應訊息中傳回來. 因此若測試 http://httpbin.org/get 的話, 呼叫 json() 方法就不會報錯了 :

>>> import urequests
>>> r=urequests.get('http://httpbin.org/get')
>>> r.json()       #可執行 json() 了
{'url': 'http://httpbin.org/get', 'headers': {'Host': 'httpbin.org', 'Connection': 'close'}, 'args': {}, 'origin': '1.172.116.121'}

GET 方法要傳遞參數的話是在網址後面用 ? 帶領參數字串. 例如在瀏覽器傳遞 a, b 參數給 GET 測試網頁 httpbin.org/get 的 URL 如下 :

http://httpbin.org/get?a=1&b=2

瀏覽器會收到如下回應 :

{
  "args": {
    "a": "1", 
    "b": "2"
  }, 
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 
    "Accept-Encoding": "gzip, deflate, sdch", 
    "Accept-Language": "zh-TW,zh;q=0.8,en-US;q=0.6,en;q=0.4", 
    "Connection": "close", 
    "Cookie": "_gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1; _gauges_unique_day=1; _gauges_unique_hour=1", 
    "Host": "httpbin.org", 
    "Upgrade-Insecure-Requests": "1", 
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 OPR/45.0.2552.898"
  }, 
  "origin": "12.174.116.121", 
  "url": "http://httpbin.org/get?a=1&b=2"
}

可見參數 a, b 會放在 args 屬性中傳回來.

在 MicroPython 測試結果如下 :

>>> import urequests
>>> r=urequests.get("http://httpbin.org/get?a=1&b=2")   #傳遞參數 a, b
>>> r.text                     #傳回 JSON 格式字串
'{\n  "args": {\n    "a": "1", \n    "b": "2"\n  }, \n  "headers": {\n    "Connection": "close", \n    "Host": "httpbin.org"\n  }, \n  "origin": "223.141.198.23", \n  "url": "http://httpbin.org/get?a=1&b=2"\n}\n'
>>> r.json()                  #呼叫 json() 方法轉成 dict 物件
{'url': 'http://httpbin.org/get?a=1&b=2', 'headers': {'Host': 'httpbin.org', 'Connection': 'close'}, 'args': {'a': '1', 'b': '2'}, 'origin': '223.141.198.23'}
>>> type(r.json())
<class 'dict'>                       #傳回值是 dict 物件
>>> r.json()['args']      #擷取 dict 物件之項目 args
{'a': '1', 'b': '2'}
>>> r.json()['args']['a']  #擷取 dict 內的屬性
'1'

以上是 GET 方法的測試, 接下來看 POST 方法, 參考 requests 官方網站的教學文件 :

http://docs.python-requests.org/en/latest/user/quickstart/#post-a-multipart-encoded-file

亦即只要呼叫 urequests.post() 方法並將要傳遞的參數設給的 data 參數即可. 在 CPython 中, 這個 data 是一個 dict 物件, 傳遞的參數是放在回應訊息的 form 屬性中傳回 :

Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> data={'a':'1','b':'2'}      #dict 物件
>>> r=requests.post("http://httpbin.org/post", data=data)
>>> r.json()
{'args': {}, 'data': '', 'files': {}, 'form': {'a': '1', 'b': '2'}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'close', 'Content-Length': '7', 'Content-Type': 'application/x-www-form-urlencoded', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.13.0'}, 'json': None, 'origin': '12.174.116.121', 'url': 'http://httpbin.org/post'}

但在 MicroPython 用 dict 物件傳送參數卻不行, 會出現 "object with buffer protocol required" 錯誤訊息. 測試結果如下 :

>>> data={'a':'1','b':'2'}       #dict 物件 (在 MicroPython 不行)
>>> r=urequests.post("http://httpbin.org/post", data=data)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "urequests.py", line 104, in post
  File "urequests.py", line 74, in request
TypeError: object with buffer protocol required  

我找到下面這篇文章, 發現其 data 不是直接用 dict 物件, 而是其字串型態 :

# HTTPS POST using urequests.py and Guru Mediation Error

我將 data 改成 dict 物件的字串結果 OK, 所傳遞的參數是放在 data 屬性中傳回來 (而不是在 form 屬性中), 而且屬性值是字串而非 dict 物件, 這樣在實際應用的後端程式 (PHP 等) 必須另外進行字串處理以擷取參數. :

>>> data="{'a':'1','b':'2'}"       #dict 物件的字串
>>> r=urequests.post("http://httpbin.org/post", data=data)
>>> r.text    
'{\n  "args": {}, \n  "data": "{\'a\':\'1\',\'b\':\'2\'}", \n  "files": {}, \n  "form": {}, \n  "headers": {\n    "Connection": "close", \n    "Content-Length": "17", \n    "Host": "httpbin.org"\n  }, \n  "json": null, \n  "origin": "223.141.198.23", \n  "url": "http://httpbin.org/post"\n}\n'
>>> r.json()                              #轉成 dict 物件  
{'files': {}, 'headers': {'Content-Length': '17', 'Host': 'httpbin.org', 'Connection': 'close'}, 'args': {}, 'form': {}, 'origin': '223.141.198.23', 'data': "{'a':'1','b':'2'}", 'json': None, 'url': 'http://httpbin.org/post'}
>>> r.json()['data']                    #data 是個字串 (不是 dict 物件)
"{'a':'1','b':'2'}"

我在下面這篇看到作者使用 json 參數而非 data 傳遞參數, 這樣就可以直接使用 dict 物件來存放欲傳遞之參數, 而且伺服器會把參數放在回應訊息的 json 屬性中傳回, 參考 :

# Building a Slack button with ESP8266/MicroPython (使用 D1 mini)

測試結果如下 :

>>> data={'a':'1','b':'2'}        #dict 物件
>>> r=urequests.post("http://httpbin.org/post", json=data)    #傳遞給 json 參數
>>> r.json()
{'files': {}, 'headers': {'Content-Length': '20', 'Host': 'httpbin.org', 'Connection': 'close'}, 'args': {}, 'form': {}, 'origin': '223.141.170.57', 'data': '{"a": "1", "b": "2"}', 'json': {'a': '1', 'b': '2'}, 'url': 'http://httpbin.org/post'}
>>> r.json()['json']['a']          #json 屬性是 dict 物件
'1'

雖然改用 json 屬性傳遞參數, 但 data 屬性還是在, 可見 data 是似乎指所有傳遞給伺服器的參數字串. 從此例可知, 若要使用 dict 物件傳資料, 則要使用 json 參數; 使用 data 參數的話, 必須將 dict 物件字串化 (序列化). 否則必須借助 json 模組的 dumps() 方法將其序列化, 參考 :

# Python爬虫利器一之Requests库的用法

測試結果如下 :

>>> import json               #匯入 json 模組
>>> import urequests   
>>> data={'a':'1','b':'2'}     #使用 dict 物件
>>> r=urequests.post('http://httpbin.org/post', data=json.dumps(data))  #dict 物件序列化
>>> r.json()
{'files': {}, 'headers': {'Content-Length': '20', 'Host': 'httpbin.org', 'Connection': 'close'}, 'args': {}, 'form': {}, 'origin': '12.174.116.121', 'data': '{"a": "1", "b": "2"}', 'json': {'a': '1', 'b': '2'}, 'url': 'http://httpbin.org/post'}

可見這與上面使用 json 參數結果是一樣的.

另外, 除了上面測試過的 data 與 json 參數外, 呼叫 urequests.post() 方法時也可以將額外的請求標頭以 dict 物件傳遞給 urequests.post() 的 headers 參數, 參考 :

# HTTP POST with Micropython and an ESP8266

但要注意, 這個 headers 參數必須是一個 dict 物件, 不可序列化, 測試結果如下 :

>>> import urequests 
>>> data="{'a':'1','b':'2'}"  
>>> headers={'content-type': 'application/json'}    #dict 物件
>>> r=urequests.post("http://httpbin.org/post", data=data, headers=headers)  
>>> r.json()    
{'files': {}, 'headers': {'Host': 'httpbin.org', 'Content-Length': '17', 'Content-Type': 'application/json', 'Connection': 'close'}, 'args': {}, 'form': {}, 'origin': '223.141.170.52', 'data': "{'a':'1','b':'2'}", 'json': None, 'url': 'http://httpbin.org/post'}

與上面沒有傳 headers 參數比較, 可知除原有的標頭外, 還多了一個 Content-Type 標頭.

最後, 我在下面這篇發現作者使用了 urequests.request() 方法來提出 GET 與 POST 請求, 而不是我們上面使用的 get() 與 post() 方法, 參考 :

# Send data requests http post. **SOLVED**

其實在 requests 官網就有此 request() 物件的說明, 參考 :

http://docs.python-requests.org/en/master/api/#main-interface

在 CPython 中可以用 params, data 或 json 傳遞參數, 用 params 傳遞的話, 參數會放在 args 屬性中傳回, 例如 :

Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> r=requests.request("GET","http://httpbin.org/get?a=1&b=2")
>>> r.json()
{'args': {'a': '1', 'b': '2'}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'close', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.13.0'}, 'origin': '12.174.116.121', 'url': 'http://httpbin.org/get?a=1&b=2'}       #參數放在 args 與 url 屬性中傳回
>>> data={'a':'1','b':'2'}     #dict 物件
>>> r=requests.request("GET","http://httpbin.org/get", params=data)   #以 params 傳送
>>> r.json()
{'args': {'a': '1', 'b': '2'}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'close', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.13.0'}, 'origin': '12.174.116.121', 'url': 'http://httpbin.org/get?a=1&b=2'}        #參數放在 args 與 url 屬性中傳回

但是用 data 或 json 的話就很奇怪, 參數似乎沒有傳遞給伺服器 (why?) :

>>> import requests
>>> data={'a':'1','b':'2'}
>>> r=requests.request("GET","http://httpbin.org/get", json=data)
>>> r.json()      #args 參數是空的, 沒有 json 參數
{'args': {}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'close', 'Content-Length': '20', 'Content-Type': 'application/json', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.13.0'}, 'origin': '12.174.116.121', 'url': 'http://httpbin.org/get'}
>>> r=requests.request("GET","http://httpbin.org/get", data=data)
>>> r.json()      #args 參數是空的, 沒有 data 參數
{'args': {}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'close', 'Content-Length': '7', 'Content-Type': 'application/x-www-form-urlencoded', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.13.0'}, 'origin': '12.174.116.121', 'url': 'http://httpbin.org/get'}

在 MicroPython 中 GET 方法則只能在 URL 中附帶字串, 不能使用 params 參數 (未實作), 而 json 與 data 參數雖可用, 但也跟 CPython 一樣沒有傳送出去 (why?), 例如 :

>>> import urequests
>>> data="{'a':'1','b':'2'}"    
>>> r=urequests.request("GET","http://httpbin.org/get", params=data)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unexpected keyword argument 'params'       #無 params 參數

可見 MicroPython 未實作 params 參數. 而用 data 參數的話雖可執行, 但參數未傳遞出去 :

>>> import urequests 
>>> data="{'a':'1','b':'2'}"    #須為字串
>>> r=urequests.request("GET","http://httpbin.org/get", data=data)
>>> r.json()
{'url': 'http://httpbin.org/get', 'headers': {'Content-Length': '17', 'Host': 'httpbin.org', 'Connection': 'close'}, 'args': {}, 'origin': '12.174.116.121'}

可見 data 參數沒傳送出去, args 屬性為空, 而 data 屬性無蹤影. 用 json 參數亦然 :

>>> import urequests 
>>> data={'a':'1','b':'2'}    #須為 dict 物件
>>> r=urequests.request("GET","http://httpbin.org/get", json=data)
>>> r.json()
{'url': 'http://httpbin.org/get', 'headers': {'Content-Length': '20', 'Host': 'httpbin.org', 'Connection': 'close'}, 'args': {}, 'origin': '12.174.116.121'}

只有使用 URL 字串附帶參數才行, 例如 :

>>> import urequests
>>> r=urequests.request('GET','http://httpbin.org/get?a=1&b=2')  #'GET' 要大寫
>>> r.json()
{'url': 'http://httpbin.org/get?a=1&b=2', 'headers': {'Host': 'httpbin.org', 'Connection': 'close'}, 'args': {'a': '1', 'b': '2'}, 'origin': '12.174.116.121'}

可見參數是放在 args 屬性中傳回來. 總之, 不論 CPython 或 MicroPython, 使用 URL 字串傳送參數是萬無一失的.

而 POST 方法也是 params 參數未實作, 只能用 data 或 json 參數, 測試結果如下 :

>>> import urequests
>>> data={'a':'1','b':'2'}       #json 參數須用 dict 物件
>>> r=urequests.request("POST","http://httpbin.org/post", json=data)
>>> r.json()
{'files': {}, 'headers': {'Content-Length': '20', 'Host': 'httpbin.org', 'Connection': 'close'}, 'args': {}, 'form': {}, 'origin': '12.174.116.121', 'data': '{"a": "1", "b": "2"}', 'json': {'a': '1', 'b': '2'}, 'url': 'http://httpbin.org/post'}
>>> data="{'a':'1','b':'2'}"    #data 參數須用字串
>>> r=urequests.request("POST","http://httpbin.org/post", data=data)
>>> r.json()
{'files': {}, 'headers': {'Content-Length': '17', 'Host': 'httpbin.org', 'Connection': 'close'}, 'args': {}, 'form': {}, 'origin': '12.174.116.121', 'data': "{'a':'1','b':'2'}", 'json': None, 'url': 'http://httpbin.org/post'}

總之, 比起 urllib.urequest 來說, urequests 模組比較簡單易用, 其中又以直接呼叫 get() 與 post() 最方便. 使用 GET 方法必須使用 URL 附帶參數方式傳遞; 而用 POST 方法則可用 data 或 json 參數傳遞.

參考 :

Micropython on ESP8266 Workshop Documentation (搜尋 HTTP Request)
MICROPYTHON ON THE ESP8266: KICKING THE TIRES
micropython/micropython-lib (MicroPython 的第三方模組)
# ESP8266 and MicroPython - Part 1
https://requestb.in/
# Send data requests http post. **SOLVED**


2017-08-31 補充 :

urequests 以 POST 方法傳遞參數時, 不論是用 data 或 json, 字典的元素都要用雙引號括起來, 不要用單引號, 實際用法參考 :

MicroPython on ESP8266 (二十一) : 使用 ThingTweet 傳送推文

2 則留言 :

Unknown 提到...

請教您:我用ESP8266的WeMos D1 Mini 開發版,3個功能:
1.max7219+3個按鈕控制8位的數碼管。
2.自動連接Wifi使用network跟ubinascii模組。
3.檢查是否連線中,並發送line訊息通知,使用requests模組。
3個個別執行都可以,整合成一個就不行,會出現錯誤(還是亂碼)
交互測試最就是2個可以同時執行,網路找好久應該是記憶體不足
因為是亂碼所以無法確定。
會是這個原因嗎?
改用EPS32能解決嗎?
謝謝

小狐狸事務所 提到...

我也不確定, 但有可能是記憶體溢位, D1 Mini 的 SRAM 是 160K, ESP32 則有 512K, 差了三倍, ESP32 開發板也不貴, 程式都一樣, 試試看即知, 我也想知道答案, 請您不吝告知, THANK YOU!