Buradaki set içinde benim en sık kullandığım İnternet Hız Testi oluyor genellikle.
Bu yüzden YZ’ye GitHub projesinin URL adresini ve ilgili sayfanın da sadece hız testi ile ilgili kısımlarını gösterip bana sadece tek tıkla İnternet hız testi yapacak bir Python betiği oluşturmasını rica ettim; sonuç tam istediğim gibi oldu.
Bence bunu da ayrı bir küçük proje olarak eklemek iyi fikir olabilir.
Hatta en iyisi bunun çok dilli (başlangıç olarak İngilizce, Türkçe) ve başka diller de eklenebilecek şekilde yapılması harika olur.
#!/usr/bin/env python3
"""
Internet Speed Test
PyQt6-based speed test tool that measures download and upload speeds
"""
from PyQt6.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLabel,
QGroupBox, QPushButton, QProgressBar, QMessageBox
)
from PyQt6.QtCore import Qt, QThread, pyqtSignal
from PyQt6.QtGui import QFont
import sys
import requests
import time
import threading
# --- NETWORK TASK WORKER ---
class NetworkTask(threading.Thread):
"""Background thread for network operations"""
def __init__(self, url, mode='dl', data=None):
super().__init__()
self.url = url
self.mode = mode
self.data = data
self.bytes_transferred = 0
self.running = True
self.daemon = True
def run(self):
try:
if self.mode == 'dl':
# Download mode
while self.running:
response = requests.get(self.url, stream=True, timeout=5)
for chunk in response.iter_content(chunk_size=8192):
if not self.running:
break
if chunk:
self.bytes_transferred += len(chunk)
elif self.mode == 'ul':
# Upload mode
while self.running:
response = requests.post(self.url, data=self.data, timeout=5)
if not self.running:
break
self.bytes_transferred += len(self.data)
except Exception:
pass
def stop(self):
self.running = False
# --- SPEED TEST WORKER ---
class SpeedTestWorker(QThread):
"""Worker thread for speed test"""
result_signal = pyqtSignal(str, str)
progress_signal = pyqtSignal(int, float)
def __init__(self):
super().__init__()
self.running = True
self.thread_count = 4
self.test_duration = 10
def run(self):
try:
# DOWNLOAD TEST
self.result_signal.emit("Status", "Measuring Download Speed...")
url = "http://speed.cloudflare.com/__down?bytes=50000000"
workers = []
for _ in range(self.thread_count):
task = NetworkTask(url, mode='dl')
task.start()
workers.append(task)
start_time = time.time()
last_bytes = 0
last_check = start_time
speed_samples = []
while time.time() - start_time < self.test_duration and self.running:
time.sleep(0.5)
now = time.time()
current_total_bytes = sum(w.bytes_transferred for w in workers)
bytes_delta = current_total_bytes - last_bytes
time_delta = now - last_check
if time_delta > 0:
instant_speed = (bytes_delta * 8) / (time_delta * 1000000)
if (now - start_time) > 2:
speed_samples.append(instant_speed)
progress = int(((now - start_time) / self.test_duration) * 100)
self.result_signal.emit("Download", f"{instant_speed:.1f} Mbps")
self.progress_signal.emit(progress, instant_speed)
last_bytes = current_total_bytes
last_check = now
for w in workers:
w.stop()
w.join(timeout=1)
final_dl_speed = 0.0
if speed_samples:
speed_samples.sort()
top_samples = speed_samples[int(len(speed_samples)*0.5):]
if top_samples:
final_dl_speed = sum(top_samples) / len(top_samples)
else:
final_dl_speed = max(speed_samples)
self.result_signal.emit("Download", f"{final_dl_speed:.2f} Mbps")
self.progress_signal.emit(100, final_dl_speed)
if not self.running:
return
time.sleep(1)
# UPLOAD TEST
self.result_signal.emit("Status", "Measuring Upload Speed...")
workers = []
data = b'0' * 524288
for _ in range(self.thread_count):
task = NetworkTask("http://speed.cloudflare.com/__up", mode='ul', data=data)
task.start()
workers.append(task)
start_time = time.time()
last_bytes = 0
last_check = start_time
speed_samples = []
while time.time() - start_time < self.test_duration and self.running:
time.sleep(0.5)
now = time.time()
current_total_bytes = sum(w.bytes_transferred for w in workers)
bytes_delta = current_total_bytes - last_bytes
time_delta = now - last_check
if time_delta > 0:
instant_speed = (bytes_delta * 8) / (time_delta * 1000000)
if (now - start_time) > 2:
speed_samples.append(instant_speed)
progress = int(((now - start_time) / self.test_duration) * 100)
self.result_signal.emit("Upload", f"{instant_speed:.1f} Mbps")
self.progress_signal.emit(progress, instant_speed)
last_bytes = current_total_bytes
last_check = now
for w in workers:
w.stop()
w.join(timeout=1)
final_ul_speed = 0.0
if speed_samples:
speed_samples.sort()
top_samples = speed_samples[int(len(speed_samples)*0.5):]
if top_samples:
final_ul_speed = sum(top_samples) / len(top_samples)
else:
final_ul_speed = max(speed_samples)
self.result_signal.emit("Upload", f"{final_ul_speed:.2f} Mbps")
self.progress_signal.emit(100, final_ul_speed)
self.result_signal.emit("Status", "Test Completed")
self.result_signal.emit("Done", "Done")
except Exception as e:
self.result_signal.emit("Error", str(e))
def stop(self):
self.running = False
# --- MAIN APPLICATION ---
class SpeedTestApp(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
self.setWindowTitle("Internet Speed Test")
self.setMinimumSize(600, 400)
layout = QVBoxLayout(self)
layout.setSpacing(20)
layout.setContentsMargins(50, 50, 50, 50)
# Title
title = QLabel("<h1 style='color:#33AADD; text-align:center'>Internet Speed Test</h1>")
title.setAlignment(Qt.AlignmentFlag.AlignCenter)
layout.addWidget(title)
# Status label
self.lbl_status = QLabel("Ready to Start")
self.lbl_status.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.lbl_status.setStyleSheet("font-size: 14pt; color: #555;")
layout.addWidget(self.lbl_status)
# Progress bar
self.progress_bar = QProgressBar()
self.progress_bar.setTextVisible(False)
self.progress_bar.setFixedHeight(10)
self.progress_bar.setStyleSheet("""
QProgressBar {
border-radius: 5px;
background: #e0e0e0;
}
QProgressBar::chunk {
background-color: #33AADD;
border-radius: 5px;
}
""")
layout.addWidget(self.progress_bar)
# Speed display boxes
speed_layout = QHBoxLayout()
# Download box
box_download = QGroupBox("Download")
box_download.setStyleSheet("font-weight: bold; padding: 10px;")
dl_layout = QVBoxLayout(box_download)
self.lbl_download = QLabel("-")
self.lbl_download.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.lbl_download.setStyleSheet("font-size: 24pt; font-weight: bold; color: #27ae60;")
dl_layout.addWidget(self.lbl_download)
# Upload box
box_upload = QGroupBox("Upload")
box_upload.setStyleSheet("font-weight: bold; padding: 10px;")
ul_layout = QVBoxLayout(box_upload)
self.lbl_upload = QLabel("-")
self.lbl_upload.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.lbl_upload.setStyleSheet("font-size: 24pt; font-weight: bold; color: #e74c3c;")
ul_layout.addWidget(self.lbl_upload)
speed_layout.addWidget(box_download)
speed_layout.addWidget(box_upload)
layout.addLayout(speed_layout)
# Start button
self.btn_start = QPushButton("🚀 START TEST")
self.btn_start.setFixedSize(220, 60)
self.btn_start.setStyleSheet("""
QPushButton {
background-color: #e67e22;
color: white;
font-size: 14pt;
border-radius: 30px;
font-weight: bold;
}
QPushButton:hover {
background-color: #d35400;
}
QPushButton:disabled {
background-color: #95a5a6;
}
""")
self.btn_start.clicked.connect(self.start_test)
layout.addStretch()
layout.addWidget(self.btn_start, alignment=Qt.AlignmentFlag.AlignCenter)
layout.addStretch()
def start_test(self):
self.btn_start.setText("Testing...")
self.btn_start.setEnabled(False)
self.progress_bar.setValue(0)
self.lbl_download.setText("-")
self.lbl_upload.setText("-")
self.worker = SpeedTestWorker()
self.worker.result_signal.connect(self.handle_result)
self.worker.progress_signal.connect(self.update_progress)
self.worker.start()
def update_progress(self, progress, speed):
self.progress_bar.setValue(progress)
def handle_result(self, result_type, value):
if result_type == "Done":
self.btn_start.setText("Restart Test")
self.btn_start.setEnabled(True)
self.progress_bar.setValue(100)
elif result_type == "Error":
QMessageBox.critical(self, "Error", value)
self.btn_start.setEnabled(True)
elif result_type == "Download":
self.lbl_download.setText(value)
elif result_type == "Upload":
self.lbl_upload.setText(value)
elif result_type == "Status":
self.lbl_status.setText(value)
def main():
app = QApplication(sys.argv)
# Set application style
app.setStyle('Fusion')
window = SpeedTestApp()
window.show()
sys.exit(app.exec())
if __name__ == '__main__':
main()