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

回答編集履歴

2

コードを追加

2018/02/13 00:47

投稿

frodo821
frodo821

スコア322

answer CHANGED
@@ -1,2 +1,40 @@
1
1
  withステートメントは`__enter__`関数と`__exit__`関数のラッパーになっていますが、この内`__enter__`関数内でエラーが発生した場合に`__exit__`関数は呼ばれません(python3.6.3で確認)。
2
- この場合は安全のために、withを使わずに明示的にオープン・クローズをした方がいいかと思います。
2
+ この場合は安全のために、withを使わずに明示的にオープン・クローズをした方がいいかと思います。
3
+ 修正例としてはこのようなコードになります。
4
+ ```python
5
+ import urllib.request
6
+
7
+ def check_status(url):
8
+ try:
9
+ response = urllib.request.urlopen(url, timeout=10)
10
+ return response.code
11
+ except urllib.error.HTTPError as e:
12
+ return e.code
13
+ except Exception as e:
14
+ print(str(e))
15
+ return -1
16
+ finally:
17
+ response.close()
18
+
19
+ status = check_status('https://www.hoge.com/')
20
+ print("access status:", status)
21
+ if status != 200:
22
+ print("access error.")
23
+ # 疎通失敗時のアクション
24
+ ```
25
+ `urlopen`関数の怖いところは、標準の`open`や`socket.socket.connect`などと違って名前解決が出来なかった、そもそもソケットが作れなかった等の場合を除きエラーが発生するときには既に接続が確立していることです。
26
+ もし、標準以外のライブラリを使うことに抵抗が無いなら`urllib`ではなく`requests`等の高水準ライブラリを使うとよいと思います。
27
+ 一応サンプルコードもおいときますね。
28
+ ```python
29
+ from requests import get
30
+
31
+ def check_status(url):
32
+ #hostが見つからない場合、404が返ります
33
+ return get(url, timeout=10).status_code
34
+
35
+ status = check_status('https://www.hoge.com/')
36
+ print("access status:", status)
37
+ if status != 200:
38
+ print("access error.")
39
+ # 疎通失敗時のアクション
40
+ ```

1

情報を追加

2018/02/13 00:47

投稿

frodo821
frodo821

スコア322

answer CHANGED
@@ -1,2 +1,2 @@
1
- withステートメントは`__enter__`関数と`__exit__`関数のラッパーになっていますが、この内`__enter__`関数内でエラーが発生した場合に`__exit__`関数は呼ばれません。
1
+ withステートメントは`__enter__`関数と`__exit__`関数のラッパーになっていますが、この内`__enter__`関数内でエラーが発生した場合に`__exit__`関数は呼ばれません(python3.6.3で確認)
2
2
  この場合は安全のために、withを使わずに明示的にオープン・クローズをした方がいいかと思います。