온라인 API에 액세스 할 수 있는지 확인하고 싶지만 인터넷에 액세스해야합니다.
파이썬을 사용하여 연결이 가능하고 활성화되어 있는지 어떻게 알 수 있습니까?
답변
아마도 당신은 다음과 같은 것을 사용할 수 있습니다 :
import urllib2
def internet_on():
try:
urllib2.urlopen('http://216.58.192.142', timeout=1)
return True
except urllib2.URLError as err:
return False
현재 216.58.192.142는 google.com의 IP 주소 중 하나입니다. 신속하게 응답 할 것으로 예상되는 사이트로 변경하십시오http://216.58.192.142
.
이 고정 IP는 google.com에 영원히 매핑되지 않습니다. 따라서이 코드는 강력하지 않습니다. 계속 작동하려면 지속적인 유지 관리가 필요합니다.
위 코드에서 FQDN (정규화 된 도메인 이름) 대신 고정 IP 주소를 사용하는 이유는 FQDN에 DNS 조회가 필요하기 때문입니다. 컴퓨터가 인터넷에 연결되어 있지 않으면 DNS 조회 자체가 urllib_request.urlopen
1 초 이상 통화를 차단할 수 있습니다 . 이것을 지적 해준 @rzetterberg에게 감사합니다.
위의 고정 IP 주소가 작동하지 않으면 다음을 실행하여 google.com (unix)의 현재 IP 주소를 찾을 수 있습니다.
% dig google.com +trace
...
google.com. 300 IN A 216.58.192.142
답변
인터넷 서버에 연결할 수 있다면 실제로 연결되어있는 것입니다. 그러나 가장 빠르고 가장 안정적인 방법을 사용하려면 모든 솔루션이 최소한 다음 요구 사항을 준수해야합니다.
- DNS 확인을 피하십시오 (우리는 잘 알려져 있고 대부분의 시간 동안 사용 가능한 IP가 필요합니다)
- 응용 프로그램 계층 연결 방지 (HTTP / FTP / IMAP 서비스에 연결)
- Python 또는 다른 언어로 외부 유틸리티를 호출하지 마십시오 (타사 솔루션에 의존하지 않는 언어에 구애받지 않는 솔루션이 필요합니다)
이를 준수하기위한 한 가지 방법은 Google의 퍼블릭 DNS 서버 중 하나에 도달 할 수 있는지 확인하는 것입니다 . 이 서버의 IPv4 주소는 8.8.8.8
및 8.8.4.4
입니다. 우리는 그들 중 하나에 연결을 시도 할 수 있습니다.
호스트의 빠른 Nmap 8.8.8.8
결과는 다음과 같습니다.
$ sudo nmap 8.8.8.8
Starting Nmap 6.40 ( http://nmap.org ) at 2015-10-14 10:17 IST
Nmap scan report for google-public-dns-a.google.com (8.8.8.8)
Host is up (0.0048s latency).
Not shown: 999 filtered ports
PORT STATE SERVICE
53/tcp open domain
Nmap done: 1 IP address (1 host up) scanned in 23.81 seconds
우리가 볼 수 있듯이, 53/tcp
개방적이고 필터링되지 않습니다. 루트가 아닌 사용자 인 경우 Nmap에 대해 sudo
또는 -Pn
인수 를 사용 하여 제작 된 프로브 패킷을 전송하고 호스트가 작동 중인지 확인하십시오.
Python을 사용하기 전에 외부 도구 인 Netcat을 사용하여 연결을 테스트 해 보겠습니다.
$ nc 8.8.8.8 53 -zv
Connection to 8.8.8.8 53 port [tcp/domain] succeeded!
netcat을 확인한다 우리가 도달 할 수있는 8.8.8.8
이상 53/tcp
. 이제 8.8.8.8:53/tcp
파이썬에서 소켓 연결을 설정하여 연결 을 확인할 수 있습니다.
import socket
def internet(host="8.8.8.8", port=53, timeout=3):
"""
Host: 8.8.8.8 (google-public-dns-a.google.com)
OpenPort: 53/tcp
Service: domain (DNS/TCP)
"""
try:
socket.setdefaulttimeout(timeout)
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
return True
except socket.error as ex:
print(ex)
return False
internet()
다른 방법은 수동으로 조작 된 DNS 프로브를 이러한 서버 중 하나에 보내고 응답을 기다리는 것입니다. 그러나 패킷 손실, DNS 확인 실패 등으로 인해 속도가 느릴 수 있다고 생각합니다. 그렇지 않으면 의견을 말하십시오.
업데이트 # 1 : @theamk의 의견 덕분에 타임 아웃은 이제 인수이며 3s
기본적으로 초기화됩니다 .
업데이트 # 2 :이 질문에 대한 모든 유효한 답변의 가장 빠르고 가장 일반적인 구현을 식별하기 위해 빠른 테스트를 수행했습니다. 요약은 다음과 같습니다.
$ ls *.py | sort -n | xargs -I % sh -c 'echo %; ./timeit.sh %; echo'
defos.py
True
00:00:00:00.487
iamaziz.py
True
00:00:00:00.335
ivelin.py
True
00:00:00:00.105
jaredb.py
True
00:00:00:00.533
kevinc.py
True
00:00:00:00.295
unutbu.py
True
00:00:00:00.546
7h3rAm.py
True
00:00:00:00.032
그리고 한 번 더 :
$ ls *.py | sort -n | xargs -I % sh -c 'echo %; ./timeit.sh %; echo'
defos.py
True
00:00:00:00.450
iamaziz.py
True
00:00:00:00.358
ivelin.py
True
00:00:00:00.099
jaredb.py
True
00:00:00:00.585
kevinc.py
True
00:00:00:00.492
unutbu.py
True
00:00:00:00.485
7h3rAm.py
True
00:00:00:00.035
True
위 출력에서 각 작성자의 모든 구현이 인터넷 연결을 올바르게 식별 함을 나타냅니다. 시간은 밀리 초 해상도로 표시됩니다.
업데이트 # 3 : 예외 처리 변경 후 다시 테스트되었습니다.
defos.py
True
00:00:00:00.410
iamaziz.py
True
00:00:00:00.240
ivelin.py
True
00:00:00:00.109
jaredb.py
True
00:00:00:00.520
kevinc.py
True
00:00:00:00.317
unutbu.py
True
00:00:00:00.436
7h3rAm.py
True
00:00:00:00.030
답변
HEAD 요청을하는 것이 더 빠르므로 HTML을 가져 오지 않습니다.
또한 Google 이이 방법을 더 좋아할 것이라고 확신합니다. 🙂
try:
import httplib
except:
import http.client as httplib
def have_internet():
conn = httplib.HTTPConnection("www.google.com", timeout=5)
try:
conn.request("HEAD", "/")
conn.close()
return True
except:
conn.close()
return False
답변
ubutnu / Kevin C 답변의 대안으로 다음 requests
과 같은 패키지를 사용합니다 .
import requests
def connected_to_internet(url='http://www.google.com/', timeout=5):
try:
_ = requests.get(url, timeout=timeout)
return True
except requests.ConnectionError:
print("No internet connection available.")
return False
보너스 : 이것은 웹 사이트를 핑하는이 기능으로 확장 될 수 있습니다.
def web_site_online(url='http://www.google.com/', timeout=5):
try:
req = requests.get(url, timeout=timeout)
# HTTP errors are not raised by default, this statement does that
req.raise_for_status()
return True
except requests.HTTPError as e:
print("Checking internet connection failed, status code {0}.".format(
e.response.status_code))
except requests.ConnectionError:
print("No internet connection available.")
return False
답변
파이썬 3.2에서 새로운 코드에 대해 unutbu가 말한 것을 업데이트하기 만하면됩니다.
def check_connectivity(reference):
try:
urllib.request.urlopen(reference, timeout=1)
return True
except urllib.request.URLError:
return False
그리고 참고로, 여기에 입력 (참조)은 확인하려는 URL입니다 : 나는 당신이 살고있는 곳에서 빠르게 연결되는 것을 선택하는 것이 좋습니다. 즉, 나는 한국에 살고 있습니다 . /www.naver.com .
답변
당신은 단지 데이터를 다운로드하려고 시도 할 수 있으며, 연결이 실패하면 연결에 문제가있는 것을 알 수 있습니다.
기본적으로 컴퓨터가 인터넷에 연결되어 있는지 확인할 수 없습니다. 잘못된 DNS 구성, 방화벽, NAT와 같은 여러 가지 실패 이유가있을 수 있습니다. 따라서 일부 테스트를 수행하더라도 시도 할 때까지 API와의 연결을 보장 할 수 없습니다.
답변
import urllib
def connected(host='http://google.com'):
try:
urllib.urlopen(host)
return True
except:
return False
# test
print( 'connected' if connected() else 'no internet!' )
파이썬 3의 경우 urllib.request.urlopen(host)