Re: Making Python Script Exit Completely with One Ctrl+C

Hongyi Zhao via curl-users <[email protected]>
Newsgroups gmane.comp.web.curl.general
Message-ID <CAGP6POLWWm_uw1oki94E0_Cy6hPYFQz1p=-CTR-X-8+wOMWn3Q@mail.gmail.com>
On Sun, Dec 10, 2023 at 10:58 AM Dan Fandrich via curl-users
<[email protected]> wrote:
>
> On Sat, Dec 09, 2023 at 01:51:13PM +0800, Hongyi Zhao via curl-users wrote:
> > Now, I try to compare the manually computed average speed and the one
> > given by pycurl in the attached script, but the latter always is 0:
> [...]
> >     try:
> >         c.perform()
> >         py_speed = c.getinfo(pycurl.SPEED_DOWNLOAD) / 1024
> >     except pycurl.error as e:
> >         pass
> >     finally:
> >         c.close()
>
> Are you sure c.perform() isn't raising an exception? That would leave py_speed
> as 0, as you are observing. Hiding exceptions like this can cause no end of
> problems when things go wrong.

The attached script does the trick:

(datasci) werner@X10DAi:~/Desktop$ python rev-3.6.py
Testing Proxy: SG_ssr_futeapbquf5m.nodelist.club_1453_018d83c677e05e71f172014fc3f45e39
Current Speed: 21.04 kB/s
Current Speed: 3726.05 kB/s
Error occurred while performing curl:  (28, 'Operation timed out after
5000 milliseconds with 29650632 out of 1073741824 bytes received')
PycURL Speed: 5791.21 kB/s
Average Speed: 5790.76 kB/s
Testing Proxy: HK_ssr_wo8o8npg4fny.nodelist.club_1303_b5bf85111d0f51c517ec7302d3f33ce1
Current Speed: 828.35 kB/s
Current Speed: 5367.13 kB/s
Error occurred while performing curl:  (28, 'Operation timed out after
5000 milliseconds with 33954720 out of 1073741824 bytes received')
PycURL Speed: 6631.92 kB/s
Average Speed: 6631.49 kB/s
Testing Proxy: SG_ssr_futeapbquf5m.nodelist.club_1354_ddfba110eddfdb7037f389e9b5917477
^CKeyboardInterrupt at line 72

But I still cannot figure out how to achieve the same purpose with the
following methods:

1. Using the following method suggested by you:

You'll probably have to block SIGINT before calling calling into pycurl, then
unblocking in the progress callback to check it, e.g.

...
signal.pthread_sigmask(signal.SIG_BLOCK, [signal.SIGINT])
c.perform()
signal.pthread_sigmask(signal.SIG_UNBLOCK, [signal.SIGINT])
...

def progress(...):
    try:
        signal.pthread_sigmask(signal.SIG_UNBLOCK, [signal.SIGINT])
    except KeyboardInterrupt:
        print('interrupted!')
        return 1
    finally:
        signal.pthread_sigmask(signal.SIG_BLOCK, [signal.SIGINT])


2. Using a pure try-expect-based method.

Regards,
Zhao

> --
> Unsubscribe: https://lists.haxx.se/mailman/listinfo/curl-users
> Etiquette:   https://curl.se/mail/etiquette.html

-- 
Unsubscribe: https://lists.haxx.se/mailman/listinfo/curl-users
Etiquette:   https://curl.se/mail/etiquette.html
rev-3.6.py (text/x-python, 2.8 KB)
import subprocess
import time
import pycurl
from io import BytesIO
import sys
import signal

def sigint_handler(signal, frame):
    print(f"KeyboardInterrupt at line {frame.f_lineno}")
    sys.exit(0)

signal.signal(signal.SIGINT, sigint_handler)

def fetch_proxies():
    command = 'echo "show stat" | sudo socat stdio /var/run/haproxy.sock 2>/dev/null | awk -F, \'$1=="socks5" && !($2~/^(FRONTEND|BACKEND)$/) {print $2,$74}\''
    try:
        process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
        output, error = process.communicate()
    except Exception as e:
        print("Error occurred while executing shell command: ", e)
        return {}

    result_dict = {}

    if error is not None:
        print("Error occurred while getting proxies status: ", error.decode('utf-8'))

    lines = output.decode('utf-8').split('\n')

    for line in lines:
        if line and len(line.split(' ')) == 2:
            key_value = line.split(' ')
            result_dict[key_value[0]] = key_value[1]

    return result_dict


def test_proxy(proxy, url):
    global last_calc_time, download_start_time, total_downloaded_data
    buffer = BytesIO()

    c = pycurl.Curl()
    c.setopt(pycurl.URL, url)
    c.setopt(pycurl.WRITEDATA, buffer)
    c.setopt(pycurl.PROXY, proxy)
    c.setopt(pycurl.PROXYTYPE, pycurl.PROXYTYPE_SOCKS5_HOSTNAME)
    c.setopt(pycurl.NOPROGRESS, False)
    c.setopt(pycurl.XFERINFOFUNCTION, progress)
    c.setopt(pycurl.TIMEOUT, 5)

    download_start_time = time.time()
    last_calc_time = download_start_time
    total_downloaded_data = 0
    py_speed = 0

    try:
        c.perform()
        total_downloaded_data = c.getinfo(pycurl.SIZE_DOWNLOAD)
    except pycurl.error as e:
        print("Error occurred while performing curl: ", e)
    finally:
        py_speed = c.getinfo(pycurl.SPEED_DOWNLOAD) / 1024
        c.close()

    elapsed_time = time.time() - download_start_time
    average_speed = total_downloaded_data / elapsed_time / 1024
    print(f"PycURL Speed: {py_speed:.2f} kB/s")

    return average_speed


def progress(download_t, download_d, upload_t, upload_d):
    global last_calc_time, download_start_time, total_downloaded_data
    current_time = time.time()

    if current_time - last_calc_time >= 2:
        elapsed_time = current_time - download_start_time
        current_speed = download_d / elapsed_time / 1024
        print(f"Current Speed: {current_speed:.2f} kB/s")
        last_calc_time = current_time

    total_downloaded_data = download_d

    return 0

proxy_data = fetch_proxies()

if not proxy_data:
    print("No proxy data found.")
    sys.exit(1)

url = "http://ipv4.download.thinkbroadband.com/1GB.zip"

for key, value in proxy_data.items():
    print(f"Testing Proxy: {key}")
    average_speed = test_proxy(value, url)
    print(f"Average Speed: {average_speed:.2f} kB/s")
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.