web前端三大主流框架之Python異步框架如何運作?

Tomorin
發布: 2018-08-16 10:06:46
原創
4014 人瀏覽過

這篇文章我們從 socket 程式設計的範例來看看 Python 非同步框架是如何運作的,需要了解下簡單的 socket 程式設計以及 Linux 提供的 I/O 復用機制。 Python 非同步框架也是基於作業系統底層提供的 I/O 重複使用機制來實現的,例如 linux 下可以使用 select/poll/epoll 等。我們先來看個簡單的 python socket server 例子,Python 程式碼使用 Python3,確保可以使用 selectors 模組。

一個實例

import socket
HOST = 'localhost'    # The remote host
PORT = 8888 # Arbitrary non-privileged port
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind((HOST, PORT))
    s.listen(50)
    while True:
        conn, addr = s.accept()
        print('Connected by', addr)
        with conn:
            while 1:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)
登入後複製

我們下邊用一個golang 的tcp client 測試下它:

package main
import (
    "fmt"
    "net"
    "os"
    "sync"
)
func sendMessage(msg string) error {
    conn, err := net.Dial("tcp", "localhost:8888")
    if err != nil {
        return fmt.Errorf("error: %v", err)
    }
    defer conn.Close()
    _, err = conn.Write([]byte("hello"))
    if err != nil {
        return fmt.Errorf("error: %v", err)
    }
    reply := make([]byte, 1024)
    _, err = conn.Read(reply)
    if err != nil {
        println("Write to server failed:", err.Error())
        os.Exit(1)
    }
    println("reply from server=", string(reply))
    return nil
}
func main() {
    var wg sync.WaitGroup
    nbGoroutines := 20
    wg.Add(nbGoroutines)
    for k := 0; k < nbGoroutines; k++ {
        go func() {
            err := sendMessage("hello")
            if err != nil {
                fmt.Printf("fail: %v\n", err)
            }
            wg.Done()
        }()
    }
    wg.Wait()
}
登入後複製

使用go 執行它可以看到輸出。

接下來我們使用 python3 提供的 selectros 來改造它,這個模組封裝了作業系統底層提供的 I/O 復用機制,例如 linux 上使用了 epoll。透過 I/O 重複使用機制我們可以監聽多個檔案描述符的可讀寫事件並且註冊回呼函數,擁有更好的並發效能。先看 python3 的 selectors 文件給的例子

import selectors
import socket
sel = selectors.DefaultSelector()
def accept(sock, mask):
    conn, addr = sock.accept()  # Should be ready
    print(&#39;accepted&#39;, conn, &#39;from&#39;, addr)
    conn.setblocking(False)
    sel.register(conn, selectors.EVENT_READ, read)
def read(conn, mask):
    data = conn.recv(1000)  # Should be ready
    if data:
        print(&#39;echoing&#39;, repr(data), &#39;to&#39;, conn)
        conn.send(data)  # Hope it won&#39;t block
    else:
        print(&#39;closing&#39;, conn)
        sel.unregister(conn)
        conn.close()
sock = socket.socket()
sock.bind((&#39;localhost&#39;, 1234))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)
while True:  # 这其实就是通常在异步框架中所说的 event loop 啦
    events = sel.select()
    for key, mask in events:
        callback = key.data
        callback(key.fileobj, mask)
登入後複製

我們來運行下這個 使用了 seelctors I/O 復用機制的 tcp echo server 看下輸出結果。

到這裡就差不多了,我們再繼續執行 go 寫的 tcp client 來測試它看結果。

在後邊教學中我們將使用python 的coroutine 而不是回呼函數來改造這個例子,這樣一來我們就能使用async/await 來運行它了


#

以上是web前端三大主流框架之Python異步框架如何運作?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板