-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNetSpeedChecker.py
More file actions
80 lines (63 loc) · 2.37 KB
/
NetSpeedChecker.py
File metadata and controls
80 lines (63 loc) · 2.37 KB
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
import asyncio
import json
from concurrent.futures import ThreadPoolExecutor
from typing import Any, Dict
import httpx
class InternetSpeedChecker:
def __init__(self):
self.client = httpx.AsyncClient(http2=True, timeout=15.0)
self.executor = ThreadPoolExecutor(max_workers=2)
self._speedtest_instance = None
async def prepare_speedtest(self):
loop = asyncio.get_running_loop()
self._speedtest_instance = await loop.run_in_executor(
self.executor, self._create_speedtest
)
def _create_speedtest(self):
from speedtest import Speedtest
st = Speedtest()
st.get_best_server()
return st
async def get_ip(self):
r = await self.client.get("https://api.ipify.org")
return r.text.strip()
async def get_location(self, ip: str):
r = await self.client.get(f"http://ip-api.com/json/{ip}")
return r.json()
def _sync_measure(self):
st = self._speedtest_instance
dl = st.download()
ul = st.upload()
return st.results.ping, dl, ul
async def measure_speed(self):
loop = asyncio.get_running_loop()
ping, dl, ul = await loop.run_in_executor(self.executor, self._sync_measure)
return ping, dl, ul
async def to_string(self, fmt: str = "json") -> str:
await self.prepare_speedtest()
ip_task = self.get_ip()
speed_task = self.measure_speed()
ip, (ping, dl, ul) = await asyncio.gather(ip_task, speed_task)
loc = await self.get_location(ip)
data = {
"Ping (ms)": round(ping, 2),
"Upload (Mbps)": round(ul / 1_000_000, 2),
"Download (Mbps)": round(dl / 1_000_000, 2),
"Country": loc.get("country", "N/A"),
"City": loc.get("city", "N/A"),
}
if fmt == "json":
return json.dumps(data, indent=4, ensure_ascii=False)
else:
from tabulate import tabulate
rows = [[k, v] for k, v in data.items()]
return tabulate(rows, headers=["Title", "Value"], tablefmt="plain", numalign="right")
async def close(self):
await self.client.aclose()
self.executor.shutdown(wait=False)
async def main():
checker = InternetSpeedChecker()
result = await checker.to_string("json")
print(result)
await checker.close()
asyncio.run(main())