回答編集履歴

3

追記

2021/06/30 23:09

投稿

katsuko
katsuko

スコア3471

test CHANGED
@@ -297,3 +297,21 @@
297
297
  `def`キーワードで定義された関数・メソッドは、callableオブジェクトになります。
298
298
 
299
299
  Pythonの内部で勝手に`__call__`が定義される、と思ってください。
300
+
301
+
302
+
303
+ ```
304
+
305
+ >>> def a():
306
+
307
+ ... pass
308
+
309
+ ...
310
+
311
+ >>> a.__call__
312
+
313
+ <method-wrapper '__call__' of function object at 0x7f64299eab80>
314
+
315
+ >>>
316
+
317
+ ```

2

コメントに関する追記

2021/06/30 23:09

投稿

katsuko
katsuko

スコア3471

test CHANGED
@@ -249,3 +249,51 @@
249
249
  これだけのことを知っていれば十分だと思いますが、`environ`の中身や、`start_response`の中の処理を知りたければ、WSGIの仕様をよく理解すべきかと思います。([この辺り](https://www.python.org/dev/peps/pep-3333/)かな?)
250
250
 
251
251
  あと、httpのプロトコルのことも理解していないのであれば、それも理解すべきです。
252
+
253
+
254
+
255
+ ---
256
+
257
+
258
+
259
+ ```python
260
+
261
+ app.run(environ, start_response(a, b))
262
+
263
+ ```
264
+
265
+
266
+
267
+ と、
268
+
269
+
270
+
271
+ ```python
272
+
273
+ app.run(environ, start_response)
274
+
275
+ ```
276
+
277
+
278
+
279
+ とでは、全く違います。
280
+
281
+
282
+
283
+ 前者は、`run`メソッドを呼び出す前に`start_response`関数を呼び出し、その戻り値を`run`メソッドに渡します。
284
+
285
+
286
+
287
+ 後者は、**`start_response`関数を呼び出していません。**
288
+
289
+ `start_response`関数そのものを渡し、**`run`メソッドの中で`start_response`関数を呼び出せるようにしています。**
290
+
291
+
292
+
293
+ > また、start_responseがcallableなオブジェクトってことであれば、どの箇所をコードからcallableだといっていますでしょうか?つまり、どこに`__call__`がありますでしょうか?
294
+
295
+
296
+
297
+ `def`キーワードで定義された関数・メソッドは、callableオブジェクトになります。
298
+
299
+ Pythonの内部で勝手に`__call__`が定義される、と思ってください。

1

コメントに対する回答

2021/06/30 23:05

投稿

katsuko
katsuko

スコア3471

test CHANGED
@@ -149,3 +149,103 @@
149
149
  httpd.serve_forever()
150
150
 
151
151
  ```
152
+
153
+
154
+
155
+ -----
156
+
157
+ コメントを受けて。
158
+
159
+
160
+
161
+ > > WSGIに対応したWebサーバ
162
+
163
+ > 具体的になんのことをいっていますでしょうか?uwsgiやビルトインサーバーのことをいっていますでしょうか?であれば、WEBサーバーではなくアプリケーションサーバーのことだと思いますが、あっていますでしょうか?
164
+
165
+
166
+
167
+ おおよそその認識で結構です。
168
+
169
+ そもそも、WEBサーバもアプリケーションサーバも、どこかの企画で決められた名称ではありませんから、意味合いも多少のズレがあると思います。
170
+
171
+ (自分も、サーバは本職ではないので、多少言葉が間違っている点もあるかもしれませんが)
172
+
173
+ 自分の場合、クライアントからのリクエストやレスポンスまで記述したので「Webサーバ」という言葉を使ったまでです。
174
+
175
+
176
+
177
+ > こちらも具体的に言うと、start_responseにはいるのは、'__name__'であっていますでしょうか?
178
+
179
+
180
+
181
+ `start_response`は、以前の回答でも書いたとおり「レスポンスを開始するために呼び出すcallableオブジェクト」です。
182
+
183
+ この説明では分かりづらいかもしれませんが、もうちょっと言い換えると「WSGIアプリケーションで、レスポンスを返すために必要な情報を渡して呼び出さなければならないcallableオブジェクト」です。
184
+
185
+ 先に挙げたサンプルコードでも呼び出していますし、flaskなどを使わないシンプルなWSGIアプリケーションのサンプルを探せば、同様に呼び出しているはずです。(それを確認する意味でも、「`wsgiref`モジュールを使って、簡単なWebアプリを作ってみては」と提案したのですが)
186
+
187
+
188
+
189
+ > もし可能でしたら、python+flask+nginx+uwsgiの構成でクライアントからリクエストがきたときにどういう処理の順番でflaskが起動するか教えて頂けますと助かります。
190
+
191
+
192
+
193
+ くり返し言いますが、「WSGIアプリケーションは、単なるcallableオブジェクトであり、(uwsgiのような)WSGIアプリケーションを起動する側は、そのcallableオブジェクトを呼び出している」だけです。
194
+
195
+
196
+
197
+ 自分はuwsgiを使ったことはありませんが、例えば[ここ](https://www.python.ambitious-engineer.com/archives/1959)を参考に、
198
+
199
+
200
+
201
+ ```
202
+
203
+ uwsgi --http=0.0.0.0:8080 --wsgi-file=run.py --callable=app
204
+
205
+ ```
206
+
207
+
208
+
209
+ と起動したとします。
210
+
211
+ 起動時に指定しているのは、pythonのスクリプト名とWSGIアプリケーションのcallableオブジェクトとなる名前(flaskのインスタンスがcallableオブジェクトになるのは先に説明したとおり)ですね。
212
+
213
+
214
+
215
+ uwsgiは、これらの情報を元に、WSGIアプリケーションを呼び出すだけです。
216
+
217
+
218
+
219
+ ```python
220
+
221
+
222
+
223
+ environ = {}
224
+
225
+ # environに、WSGIの仕様に従った情報を設定
226
+
227
+ def start_response(status, headers):
228
+
229
+ # 渡されたstatusとヘッダ情報を元に、httpのヘッダを送信
230
+
231
+ pass
232
+
233
+
234
+
235
+ # こんな単純なimportではないと思いますが、そこは長くなるし、WSGIとは関係のないことなので省略
236
+
237
+ import run
238
+
239
+ response = run.app(environ, start_response)
240
+
241
+
242
+
243
+ # responseを元に、httpのボディを送信
244
+
245
+ ```
246
+
247
+
248
+
249
+ これだけのことを知っていれば十分だと思いますが、`environ`の中身や、`start_response`の中の処理を知りたければ、WSGIの仕様をよく理解すべきかと思います。([この辺り](https://www.python.org/dev/peps/pep-3333/)かな?)
250
+
251
+ あと、httpのプロトコルのことも理解していないのであれば、それも理解すべきです。