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 <CAGP6POLcrg8Cayi=OAKsfNtL6NDZaER1bFf77+WWDx_BqZFvCg@mail.gmail.com>
On Fri, Dec 8, 2023 at 10:44 AM Dan Fandrich via curl-users
<[email protected]> wrote:
>
> On Fri, Dec 08, 2023 at 09:56:44AM +0800, Hongyi Zhao via curl-users wrote:
> > I tried the following method but in vain:
> [...]
> >     try:
> >         pass
> >     except KeyboardInterrupt:
> >         kb_interrupt = True
>
> This won't accomplish anything because "pass" will never raise an exception.
> I have a feeling that even putting the entire contents of the progress callback
> into a try/except block won't even help; I suspect the exception is raised the
> moment the Python interpreter is returned to by pycurl while calling that
> callback, which is before even that point.
>
> 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])
>
> or just set your own SIGINT handler that sets a flag (kb_interrupt), then check
> that flag in the progress callback and return an error if it's set.

I tried using the first method of your tips. It works, but the
calculated *Average Speed* is too high, as shown below:

(datasci) werner@X10DAi:~/Desktop$ python callback-SIGINT.py
Proxy: SG_ssr_futeapbquf5m.nodelist.club_1453_018d83c677e05e71f172014fc3f45e39
Current Speed: 1371.74 kB/s
Current Speed: 6565.90 kB/s
Average Speed: 7552.72 kB/s
Proxy: HK_ssr_wo8o8npg4fny.nodelist.club_1303_b5bf85111d0f51c517ec7302d3f33ce1
Current Speed: 1252.55 kB/s
Current Speed: 7461.93 kB/s
Average Speed: 8807.27 kB/s
Proxy: SG_ssr_futeapbquf5m.nodelist.club_1354_ddfba110eddfdb7037f389e9b5917477
Current Speed: 3081.76 kB/s
Current Speed: 9351.58 kB/s
Average Speed: 10745.23 kB/s
Proxy: HK_ssr_fwqvvo60u1mj.nodelist.club_1423_dba3b0996744e7b82eae7634626a5ba9
^Cinterrupted!
Average Speed: 156.74 kB/s
Proxy: SG_ssr_futeapbquf5m.nodelist.club_1356_8ce27b1301fcbcb77cc5abb28cb127a6
Script terminated by user. Exiting.

I'm not sure how to fix this problem. Attached please find the test script.

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
callback-SIGINT.py (text/x-python, 2.6 KB)
import subprocess
import time
import pycurl
import signal
from io import BytesIO
import sys


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}\''
    process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
    output, error = process.communicate()

    result_dict = {}

    if error is not None:
        return result_dict

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

    for line in lines:
        if line != "":
            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, kb_interrupt

    kb_interrupt = False

    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

    signal.pthread_sigmask(signal.SIG_BLOCK, [signal.SIGINT])

    try:
        c.perform()
    except pycurl.error as e:
        pass

    signal.pthread_sigmask(signal.SIG_UNBLOCK, [signal.SIGINT])

    average_speed = c.getinfo(pycurl.SPEED_DOWNLOAD) / 1024
    return average_speed


def progress(download_t, download_d, upload_t, upload_d):
    global last_calc_time, download_start_time, kb_interrupt
    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

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

proxy_data = fetch_proxies()
url = "http://ipv4.download.thinkbroadband.com/1GB.zip"

kb_interrupt = False

for key, value in proxy_data.items():
    print(f"Proxy: {key}")

    if kb_interrupt:
        print("Script terminated by user. Exiting.")
        sys.exit(0)

    try:
        average_speed = test_proxy(value, url)
        print(f"Average Speed: {average_speed:.2f} kB/s")
    except KeyboardInterrupt:
        print("Keyboard interrupt encountered during proxy testing. Exiting.")
        break
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.