使用多线程的Python url请求



我的要求之一是为整个文件夹中的每个视频发送上传请求。

如何将其更改为多线程请求?

我的想法是导入线程,目的是上传到aws-s3。

import requests
import base64
import hashlib
import os
tools_dir = os.path.dirname(os.path.realpath(__file__))
project_root = os.path.dirname(tools_dir)
videos_dir = os.path.join(project_root, "output", "videos")
# Basic auth settings
basic_auth_user = "abc123"
basic_auth_password = "abc456"
auth = (basic_auth_user + ":" + basic_auth_password)
# Base64 encode and decode
auth_encode_format = auth.encode("utf-8")
auth_encode_base64 = base64.b64encode(auth_encode_format)
auth_encode_base64_format = auth_encode_base64.decode("utf-8")
str1 = "_"
for file in os.listdir(videos_dir):
# print(file[0:10:])
# print(file[:file.index(str1)])
serial_number = file[:file.index(str1)]
# print(f'{serial_number}')
m = hashlib.md5()
with open(os.path.join(videos_dir, file), 'rb') as f:
for chunk in iter(lambda: f.read(4096), b""):
m.update(chunk)
h = m.hexdigest()
url = "http://localhost:8000/api/awss3/upload"
payload = {
'fileHash': f'{h}',
'device': {'serialNumber':f'{serial_number}'}
}
files = [('file', (f'{file}', open(os.path.join(videos_dir, file), 'rb'), 'application/octet-stream'))]
headers = {
'Authorization': f'Basic {auth_encode_base64_format}'
}
response = requests.request("POST", url, headers = headers, data = payload, files = files)
print("n" + response.text)

将无副作用的基于循环的代码(如这里的代码(转换为多线程代码的最简单方法是改用基于map的方法。然后,您可以使用线程或进程池,而不需要自己手动管理线程。

这是您目前代码的大致近似值:

for file_path in big_list_of_files:
...

您可以通过将逻辑从循环中拉到函数中作为中间步骤来实现这一点:

def upload_file(file_path):
...
for file_path in big_list_of_files:
upload_file(file_path)

使得切换到基于地图的方法变得容易。上传文件是IO绑定的,而不是CPU绑定的,所以您可能想要使用multiprocessing.dummy,这是使用线程而不是进程的multiprocessing模块的实现。在这种情况下,4是要使用的线程数:

from multiprocessing.dummy import Pool
def upload_file(file_path):
...
with Pool(4) as thread_pool:
thread_pool.map(upload_file, big_list_of_files)

如果你正在将文件上传到S3,最好考虑使用亚马逊的boto3库,这将简化你的代码,并自动执行校验和验证,并对更大的文件使用多部分上传。