curl / Mailing Lists / curl-library / Single Mail
Buy commercial curl support from WolfSSL. We help you work out your issues, debug your libcurl applications, use the API, port to new platforms, add new features and more. With a team lead by the curl founder himself.

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

From: Dave S via curl-library <curl-library_at_lists.haxx.se>
Date: Fri, 15 Dec 2023 00:26:50 -0800

On Thu, Dec 7, 2023, 2:46 AM Hongyi Zhao via curl-library <
curl-library_at_lists.haxx.se> wrote:

> Dear libcurl community,
>
> I hope this message finds you in good health. I am reaching out to
> seek your assistance regarding an issue that I have been experiencing
> with one of my Python scripts that involves the use of libcurl.
>
> The script, named **proxy-speed.py**, is employed to measure and
> display the speed of different proxies. It runs through a list of
> proxies, giving the current and average speed for each, one at a time.
> However, the issue arises when I try to terminate the script
> prematurely using Ctrl+C. The KeyboardInterrupt appears to only pause
> the current task, and the script instantaneously proceeds with the
> next proxy on the list, clearly illustrating that it doesn’t exit
> entirely.
>
> Here’s an example illustrating the issue:
>
>
> ```
> File "/home/werner/Desktop/proxy-speed/proxy-speed.py", line 54, in
> progress
> def progress(download_t, download_d, upload_t, upload_d):
>
> KeyboardInterrupt
> Average Speed: 3944.97 kB/s
>
> Proxy:
> SG_ssr_futeapbquf5m.nodelist.club_1356_8ce27b1301fcbcb77cc5abb28cb127a6
> ^CTraceback (most recent call last):
> File "/home/werner/Desktop/proxy-speed/proxy-speed.py", line 54,
> in progress
> def progress(download_t, download_d, upload_t, upload_d):
>
> KeyboardInterrupt
> Average Speed: 72.81 kB/s
> ```
> This repeat pattern continues for every Ctrl+C interruption made.
> Hence, my goal is to modify the script so that a single Ctrl+C command
> would result in a comprehensive termination of the script.
>
> Any guidance or suggestions that you could offer regarding this issue
> would be greatly appreciated. If there is any further information
> needed to better understand the issue, please let me know.
>
> The content of **proxy-speed.py** is as follows:
>
> ```
> import subprocess
> import time
> import pycurl
> from io import BytesIO
>
> 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 = {} # Initialize default empty dictionary
>
> if error is not None:
> return result_dict # Return the empty dictionary in case of error
>
> 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
>
> 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
>
> try:
> c.perform()
> except pycurl.error as e:
> pass
> except KeyboardInterrupt:
> print("Script interrupted by user. Exiting.")
> sys.exit(0) # immediately exit the script
>
> 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
> 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
>
> proxy_data = fetch_proxies()
> url = "http://ipv4.download.thinkbroadband.com/1GB.zip"
>
> for key, value in proxy_data.items():
> print(f"Proxy: {key}")
> try:
> average_speed = test_proxy(value, url)
> print(f"Average Speed: {average_speed:.2f} kB/s")
> except KeyboardInterrupt:
> print("Script interrupted by user. Exiting.")
> break # exit the for loop
> ```
>
> Thank you very much for your help in advance.
>
> Best Regards,
> Zhao
>
> P.S: If possible, could you please provide both an explanation and
> snippet of the solution so that I can understand and learn from it for
> future references.
> --
> Assoc. Prof. Hongsheng Zhao <hongyi.zhao_at_gmail.com>
> Theory and Simulation of Materials
> Hebei Vocational University of Technology and Engineering
> No. 473, Quannan West Street, Xindu District, Xingtai, Hebei province
> --
> Unsubscribe: https://lists.haxx.se/mailman/listinfo/curl-library
> Etiquette: https://curl.se/mail/etiquette.html




Since your exception handler doesn't seem to print it's message, and
another message is printed, I suspect the keyboard interrupt exception is
being handled without being raised to your routine.

I don't ctrl-c out of my python scripts often, and mostly do it on Windows,
so I don't have a more complete explanation.

Good luck with the hunting.

Dave S
/DPS


-- 
Unsubscribe: https://lists.haxx.se/mailman/listinfo/curl-library
Etiquette:   https://curl.se/mail/etiquette.html
Received on 2023-12-15