teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

追記

2021/06/30 23:09

投稿

katsuko
katsuko

スコア3601

answer CHANGED
@@ -147,4 +147,13 @@
147
147
  > また、start_responseがcallableなオブジェクトってことであれば、どの箇所をコードからcallableだといっていますでしょうか?つまり、どこに`__call__`がありますでしょうか?
148
148
 
149
149
  `def`キーワードで定義された関数・メソッドは、callableオブジェクトになります。
150
- Pythonの内部で勝手に`__call__`が定義される、と思ってください。
150
+ Pythonの内部で勝手に`__call__`が定義される、と思ってください。
151
+
152
+ ```
153
+ >>> def a():
154
+ ... pass
155
+ ...
156
+ >>> a.__call__
157
+ <method-wrapper '__call__' of function object at 0x7f64299eab80>
158
+ >>>
159
+ ```

2

コメントに関する追記

2021/06/30 23:09

投稿

katsuko
katsuko

スコア3601

answer CHANGED
@@ -123,4 +123,28 @@
123
123
  ```
124
124
 
125
125
  これだけのことを知っていれば十分だと思いますが、`environ`の中身や、`start_response`の中の処理を知りたければ、WSGIの仕様をよく理解すべきかと思います。([この辺り](https://www.python.org/dev/peps/pep-3333/)かな?)
126
- あと、httpのプロトコルのことも理解していないのであれば、それも理解すべきです。
126
+ あと、httpのプロトコルのことも理解していないのであれば、それも理解すべきです。
127
+
128
+ ---
129
+
130
+ ```python
131
+ app.run(environ, start_response(a, b))
132
+ ```
133
+
134
+ と、
135
+
136
+ ```python
137
+ app.run(environ, start_response)
138
+ ```
139
+
140
+ とでは、全く違います。
141
+
142
+ 前者は、`run`メソッドを呼び出す前に`start_response`関数を呼び出し、その戻り値を`run`メソッドに渡します。
143
+
144
+ 後者は、**`start_response`関数を呼び出していません。**
145
+ `start_response`関数そのものを渡し、**`run`メソッドの中で`start_response`関数を呼び出せるようにしています。**
146
+
147
+ > また、start_responseがcallableなオブジェクトってことであれば、どの箇所をコードからcallableだといっていますでしょうか?つまり、どこに`__call__`がありますでしょうか?
148
+
149
+ `def`キーワードで定義された関数・メソッドは、callableオブジェクトになります。
150
+ Pythonの内部で勝手に`__call__`が定義される、と思ってください。

1

コメントに対する回答

2021/06/30 23:05

投稿

katsuko
katsuko

スコア3601

answer CHANGED
@@ -73,4 +73,54 @@
73
73
  with make_server('', 8000, app) as httpd:
74
74
  print("Serving on port 8000...")
75
75
  httpd.serve_forever()
76
- ```
76
+ ```
77
+
78
+ -----
79
+ コメントを受けて。
80
+
81
+ > > WSGIに対応したWebサーバ
82
+ > 具体的になんのことをいっていますでしょうか?uwsgiやビルトインサーバーのことをいっていますでしょうか?であれば、WEBサーバーではなくアプリケーションサーバーのことだと思いますが、あっていますでしょうか?
83
+
84
+ おおよそその認識で結構です。
85
+ そもそも、WEBサーバもアプリケーションサーバも、どこかの企画で決められた名称ではありませんから、意味合いも多少のズレがあると思います。
86
+ (自分も、サーバは本職ではないので、多少言葉が間違っている点もあるかもしれませんが)
87
+ 自分の場合、クライアントからのリクエストやレスポンスまで記述したので「Webサーバ」という言葉を使ったまでです。
88
+
89
+ > こちらも具体的に言うと、start_responseにはいるのは、'__name__'であっていますでしょうか?
90
+
91
+ `start_response`は、以前の回答でも書いたとおり「レスポンスを開始するために呼び出すcallableオブジェクト」です。
92
+ この説明では分かりづらいかもしれませんが、もうちょっと言い換えると「WSGIアプリケーションで、レスポンスを返すために必要な情報を渡して呼び出さなければならないcallableオブジェクト」です。
93
+ 先に挙げたサンプルコードでも呼び出していますし、flaskなどを使わないシンプルなWSGIアプリケーションのサンプルを探せば、同様に呼び出しているはずです。(それを確認する意味でも、「`wsgiref`モジュールを使って、簡単なWebアプリを作ってみては」と提案したのですが)
94
+
95
+ > もし可能でしたら、python+flask+nginx+uwsgiの構成でクライアントからリクエストがきたときにどういう処理の順番でflaskが起動するか教えて頂けますと助かります。
96
+
97
+ くり返し言いますが、「WSGIアプリケーションは、単なるcallableオブジェクトであり、(uwsgiのような)WSGIアプリケーションを起動する側は、そのcallableオブジェクトを呼び出している」だけです。
98
+
99
+ 自分はuwsgiを使ったことはありませんが、例えば[ここ](https://www.python.ambitious-engineer.com/archives/1959)を参考に、
100
+
101
+ ```
102
+ uwsgi --http=0.0.0.0:8080 --wsgi-file=run.py --callable=app
103
+ ```
104
+
105
+ と起動したとします。
106
+ 起動時に指定しているのは、pythonのスクリプト名とWSGIアプリケーションのcallableオブジェクトとなる名前(flaskのインスタンスがcallableオブジェクトになるのは先に説明したとおり)ですね。
107
+
108
+ uwsgiは、これらの情報を元に、WSGIアプリケーションを呼び出すだけです。
109
+
110
+ ```python
111
+
112
+ environ = {}
113
+ # environに、WSGIの仕様に従った情報を設定
114
+ def start_response(status, headers):
115
+ # 渡されたstatusとヘッダ情報を元に、httpのヘッダを送信
116
+ pass
117
+
118
+ # こんな単純なimportではないと思いますが、そこは長くなるし、WSGIとは関係のないことなので省略
119
+ import run
120
+ response = run.app(environ, start_response)
121
+
122
+ # responseを元に、httpのボディを送信
123
+ ```
124
+
125
+ これだけのことを知っていれば十分だと思いますが、`environ`の中身や、`start_response`の中の処理を知りたければ、WSGIの仕様をよく理解すべきかと思います。([この辺り](https://www.python.org/dev/peps/pep-3333/)かな?)
126
+ あと、httpのプロトコルのことも理解していないのであれば、それも理解すべきです。