-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNetSpeedChecker.py
More file actions
78 lines (64 loc) · 2.41 KB
/
Copy pathNetSpeedChecker.py
File metadata and controls
78 lines (64 loc) · 2.41 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
import asyncio
import json
from concurrent.futures import ThreadPoolExecutor
import httpx
class InternetSpeedChecker:
def __init__(self):
self.client = httpx.AsyncClient(http2=False, timeout=15.0)
self.executor = ThreadPoolExecutor(max_workers=1)
self._st = None
async def _prepare_speedtest(self):
loop = asyncio.get_running_loop()
self._st = await loop.run_in_executor(self.executor, self._create_speedtest)
@staticmethod
def _create_speedtest():
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._st
dl = st.download()
ul = st.upload()
return st.results.ping, dl, ul
async def measure_speed(self):
loop = asyncio.get_running_loop()
return await loop.run_in_executor(self.executor, self._sync_measure)
async def to_string(self, fmt: str = "json") -> str:
prep_task = asyncio.create_task(self._prepare_speedtest())
ip_task = asyncio.create_task(self.get_ip())
await prep_task
speed_task = asyncio.create_task(self.measure_speed())
ip = await ip_task
loc_task = asyncio.create_task(self.get_location(ip))
ping, dl, ul = await speed_task
loc = await loc_task
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()
if __name__ == "__main__":
asyncio.run(main())