import os
import shutil
from urllib.request import ProxyHandler, build_opener

proxy = 'http://proxy.example.net:8080'
opener = build_opener(ProxyHandler({
    'http': proxy,
    'https': proxy,
}))

temporary = 'archive.zip.part'
destination = 'archive.zip'

with opener.open('https://downloads.example.net/archive.zip',
                 timeout=20) as response:
    with open(temporary, 'wb') as output:
        shutil.copyfileobj(response, output)

os.replace(temporary, destination)

Replace the URLs and filenames for the application. For a permitted public-file download without proxy authentication, the HTTP proxy list can supply candidate endpoints for the proxy URL. This dedicated urllib opener uses an HTTP proxy for an HTTPS destination with normal certificate verification. It does not install a global opener; authentication, if needed, requires its supported setup.

copyfileobj copies in chunks. Exiting the file context closes it and flushes buffered writes before os.replace installs the final name.

If requesting or copying raises, the rename is skipped. A partial file may remain for the cleanup policy, and this flow leaves an existing final file untouched on that failure. On success, replace can overwrite that final file, so choose the policy deliberately.

Use unique temporary names for concurrent jobs. Separate opener objects do not protect jobs sharing the same .part path.

The 20-second setting bounds supported socket operations rather than total download time. A whole-job deadline needs separate application handling. Transfer completion is also separate from verifying the downloaded artifact.

Erthyglow kevrennek