试试python japronto


1.日本

我看到有关japronto在各种站点上运行速度很快的文章。
如果您仍然这样做,则过程越快越好。达到可以在当前工作中使用当前技能的水平
我暂时尝试一下,看看是否可以实现。

2.安装

在Windows上安装时出现错误。将其安装在WSL等上并使用。

1
pip install japronto

顺便说一下,我的环境如下。

<表格>

类别




<身体>

操作系统

Ubuntu 18.04(WSL)

python

Python 3.7.2


3. Hello World

1
2
3
4
5
6
7
8
9
10
from japronto import Application

def hello(request):
    return request.Response(text='Hello world!')

app = Application()

app.router.add_route('/', hello)

app.run(host='127.0.0.1',port=7777)

4.负载测试

*重写。

它非常快,因此我实际上使用已知的每个Hello World对其进行了测量。

1个来源

1个Python Responder

1
2
3
4
5
6
7
8
9
10
import responder

api = responder.API()

@api.route("/")
async def hello_world(req, resp):
    resp.text = "hello world"

if __name__ == '__main__':
    api.run()

2 python japronto

1
2
3
4
5
6
7
8
9
10
from japronto import Application

def hello(request):
    return request.Response(text='Hello world!')

app = Application()

app.router.add_route('/', hello)

app.run(host='127.0.0.1',port=7777)

3长生不老药凤凰

1
2
3
4
5
6
7
8
defmodule HelloworldWeb.PageController do
  use HelloworldWeb, :controller

  def index(conn, _params) do
    # render(conn, "index.html")
    text conn, "Hello World"
  end
end

4 PHP Phalcon

1
2
3
4
5
6
7
8
<?php

$response = new \Phalcon\Http\Response();

$response->setStatusCode(200, "OK");
$response->setContent("Hello world");

$response->send();

5锈actix_web

1
2
3
4
5
6
7
8
9
10
11
12
13
extern crate actix_web;
use actix_web::{server, App, HttpRequest};

fn index(_req: &HttpRequest) -> &'static str {
    "Hello world!"
}

fn main() {
    server::new(|| App::new().resource("/", |r| r.f(index)))
        .bind("127.0.0.1:8088")
        .unwrap()
        .run();
}

2指令

1
ab -c 100 -n 1000 http://localhost:XXXX

3. result

<表格>

python响应器

python japronto

长虹凤凰

php phalcon

锈actix-web


<身体>

服务器软件

uvicorn

牛仔

Apache


文档长度

11个字节

12个字节

11个字节

11个字节

12个字节

并发级别

100

100

100

100

100

测试所需的时间

2.447秒

0.344秒

2.421秒

5.469秒

1.298秒

完成请求

1000

1000

1000

1000

1000

请求失败

0

0

0

0

0

传输总数

147000字节

92000字节

449000字节

189000字节

129000字节

已传输HTML

11000字节

12000字节

11000字节

11000字节

12000字节

每秒的请求

408.65#/秒

2909.80#/秒

413.10#/秒

182.86#/秒

770.26#/秒

每个请求的时间

244.705 ms

34.367毫秒

242.070毫秒

546.871毫秒

129.826毫秒

每个请求的时间

2.447毫秒

0.344毫秒

2.421毫秒

5.469毫秒

1.298毫秒

传输速率

接收到58.66 [Kbytes / sec]

接收到261.43 [KB / s]

收到181.14 [KB /秒]

接收到33.75 [Kbytes / sec]

接收到97.03 [Kbytes / sec]


5.基本

示例中。请参考这里。

6.已实施的应用

它没有其他框架的功能。在这里,我将发布创建的应用程序。

(1)。模板引擎

使用Jinja2

1
2
3
4
5
6
7
8
9
10
11
12
13
│  main.py
│  
├─static
│  ├─css
│  │      a.css
│  │      w2ui.min.css
│  │      
│  └─js
│          jquery-3.2.1.min.js
│          w2ui.min.js
│          
└─templates
       index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from japronto import Application
from jinja2 import Template

def get_jinja2_template(filename):
    with open(filename) as html_file:
        return Template(html_file.read())

def jinja2(request):
    template = get_jinja2_template('index.html')
    return request.Response(text=template.render(name='Jinja2'),
                            mime_type='text/html')

app = Application()

app.router.add_route('/', jinja2)

app.run(host='127.0.0.1', port=7777)

index.html

1
2
3
4
5
6
7
8
9
10
11
12
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  japronto
  <meta name="description" content="japronto">
</head>
<body>
  <h1>Hello World!</h1>
  <p>Behold, the power of japronto!</p>
</body>
</html>

(2)。静态文件

我想知道是否也必须实现一个静态文件?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from japronto import Application

async def static(request):
    with open(request.path[1:], 'rb') as static_file:
        return request.Response(body=static_file.read())

def index(request):
    return request.Response(
        text=
        '<link rel="stylesheet" href="/static/css/main.css">' \
        '<script type="text/javascript" src="/static/js/jquery-3.2.1.min.js"></script>' \
        '<h1>Hello World</h1>',
        mime_type='text/html')

app = Application()

app.router.add_route('/', index)
# staticの下の階層が2
app.router.add_route('/static/{1}/{2}', static)
app.run(host='127.0.0.1', port=7777)

(3)。数据库

如果您要逐事务连接到数据库,则会破坏japronto的快速响应。
使用连接池支持与数据库的连接。

安装并添加软件包

1
2
3
sudo apt-get install -y python3-dev
sudo apt-get install -y libpq-dev
pip install psycopg2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import psycopg2
import psycopg2.extras
import psycopg2.pool
from japronto import Application

def resultset_as_dict(sql):
    conn = connection_pool.getconn()
    cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
    cur.execute (sql)
    results = cur.fetchall()
    dict_result = []
    for row in results:
        dict_result.append(dict(row))
    cur.close()
    connection_pool.putconn(conn)
    return dict_result

def hello(request):
    dict_result = resultset_as_dict('select * from User')
    print(dict_result)
    return request.Response(text='Hello world!')

connection_pool = psycopg2.pool.SimpleConnectionPool(
    minconn=10, maxconn=50,
    host="localhost", port="5432",
    dbname="postgres", user="testuser", password="testuser")

app = Application()

app.router.add_route('/', hello)

app.run(host='127.0.0.1',port=7777)

基准

即使100个人同时访问1000次,该速度也很快。

1
2
3
4
5
6
7
8
9
10
11
h2load -p http/1.1  -c 100 -n 1000 http://localhost:7777
starting benchmark...
finished in 1.49s, 670.75 req/s, 60.26KB/s
requests: 1000 total, 1000 started, 1000 done, 1000 succeeded, 0 failed, 0 errored, 0 timeout
status codes: 1000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 89.84KB (92000) total, 51.76KB (53000) headers (space savings 0.00%), 11.72KB (12000) data
                     min         max         mean         sd        +/- sd
time for request:     6.77ms    218.46ms    133.15ms     53.95ms    55.80%
time for connect:     2.56ms     20.35ms     11.32ms      5.02ms    59.00%
time to 1st byte:    14.83ms    238.81ms    156.18ms     57.93ms    57.00%
req/s           :       6.73       10.02        7.53        0.82    82.00%

(4)。文件下载

文件下载可在Response的body参数中设置文件对象。
之后,如果根据文件类型设置了mimetype,就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from japronto import Application
import urllib

import os
from pathlib import Path

download_path=os.path.join(Path(__file__).resolve().parents[0], 'download')

def get_file(filename):
    fpath = os.path.join(download_path, filename)
    with open(fpath, 'rb') as f:
        return f.read()
    return

def excel(request):
    excel_file=get_file('report.xlsx')
    return request.Response(body=excel_file,
        mime_type='application/vnd.ms-excel'
        )

def pdf(request):
    pdf_file=get_file('sample.pdf')
    return request.Response(body=pdf_file,
        mime_type='application/force-download'
        )

app = Application()

app.router.add_route('/excel/report.xlsx', excel)
app.router.add_route('/pdf/sample.pdf', pdf)

app.run(host='127.0.0.1',port=7777)

(5)。文件上传

对于文件上传,数据将存储在请求的文件中。
此外,japronto必须正确设置表单的enctype
请注意,files属性设置不正确。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from japronto import Application

def get(request):
    return request.Response(
        text='<form method="post" enctype="multipart/form-data">' \
        '<input type="file" name="upload_file" /><br/>' \
        '<input type="submit" value="送信" /><br/>' \
        '</form>',
        mime_type='text/html')

def post(request):
    files=request.files
    if 'upload_file' in files:
        upload_data = files['upload_file']
        upload_file = upload_data.body
        upload_name = upload_data.name
        outfile = open('upload/%s' % upload_name, 'wb')
        outfile.write(upload_file)
    return request.Response(text='OK')

app = Application()

app.router.add_route('/', get, method="GET")
app.router.add_route('/', post, method="POST")

app.run(host='127.0.0.1',port=7777)

(6)。用户认证

用户身份验证。最初,单独需要以下实现,但是将其省略。
-最初,实现用户名是为了检查User表的存在,但是
在这里,如果登录用户是admin,则可以。

  • 登录身份验证完成后,在词典中设置SessionID,但是在注销时
    由于会话超时而在字典中删除或删除会话ID等处理
    单独需要。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
from japronto import Application
from http.cookies import SimpleCookie
import hashlib
import datetime
import time

sessions = {}

# todo session timeout
timeout_minute=30

def is_user(username, password):
    if (username=='admin'):
        return True
    return False

def create_sessionid(userid):
    # sessionを生成
    session_id = hashlib.sha256(userid.encode()).hexdigest()
    # sessionは、辞書内に管理する。
    sessions[session_id] = userid
    return session_id

def redirect(request, url, cookies=None):
    return request.Response(headers={'Location': url}, code=302, cookies=cookies)

def loginhtml(message=None):
    return '' \
        '<h1>Login</h1>' \
        '<div>%s</div>' \
        '<form method="post" enctype="application/x-www-form-urlencoded">' \
        '<label>username:</label><br/>' \
        '<input type="text" name="username" required/><br/>' \
        '<br/>' \
        '<label>password:</label><br/>' \
        '<input type="password" name="password" required/><br/>' \
        '<br/>' \
        '<input type="submit" value="送信"/>' \
        '</form>' \
        '<br/>' % message

def tophtml(username, message=None):
    return '' \
        '<h1>Dash Board</h1>' \
        '<div>%s</div>' \
        'welcome to %s' \
        '<br/>' % (message, username)

# Views handle logic, take request as a parameter and
# returns Response object back to the client
def login(request):
    html = loginhtml('ログインしてください。')
    return request.Response(text=html, mime_type='text/html')

def login_post(request):
    form = request.form
    username=form['username']
    password=form['password']

    if is_user(username, password):
        session_id = create_sessionid(username)
        cookies = SimpleCookie()
        cookies['SessionID'] = session_id
        return redirect(request, '/', cookies)
    else:
        html = loginhtml('ユーザIDまたはパスワードが違います')
        return request.Response(text=html, mime_type='text/html')

def index(request):
    if 'Cookie' in request.headers:
        cookies = SimpleCookie()
        cookies.load(request.headers['Cookie'])
        if 'SessionID' in cookies:
            session_id = cookies['SessionID'].value
            if session_id in sessions:
                userid = sessions[session_id]
                html = tophtml(userid, 'こんにちは')
                return request.Response(text=html, mime_type='text/html', cookies=cookies)
    # 未ログインの状態
    return redirect(request, '/login')

app = Application()

app.router.add_route('/', index, method='GET')
app.router.add_route('/login', login, method='GET')
app.router.add_route('/login', login_post, method='POST')

app.run(host='127.0.0.1', port=7777)

7.总结

Japroto速度很快,尽管它是Python,但我认为即使在高负载环境下,它也能快速运行。
另一方面,它不是像Django或Flask这样的全栈框架,因此需要大量实现。

不幸的是,japronto似乎仍然是alpha版本。

1
2
3
This is an early preview with alpha quality implementation.
APIs are provisional meaning that they will change between versions and more testing is needed.
Don't use it for anything serious for now and definitely don't use it in production. Please try it though and report back feedback. If you are shopping for your next project's framework I would recommend Sanic.

在此领域,最好通过选择要为每个需求选择的框架来开发系统。