Использование Linux и Python 2.7.6 У меня есть сценарий, который загружает много файлов за один раз. Я использую многопоточность с модулями Queue и Threading.Python Daemon Thread Clean Up Logic on Abrupt sys.exit()
Я реализовал обработчик для SIGINT, чтобы остановить скрипт, если пользователь нажимает ctrl-C. Я предпочитаю использовать потоки демона, поэтому мне не нужно очищать очередь, что потребует много повторного написания кода, чтобы заставить обработчик SIGINT иметь доступ к объекту Queue, поскольку обработчики не принимают параметры.
Чтобы убедиться, что потоки daemon закончены и очищены до sys.exit(), я использую threading.Event() и threading.clear(), чтобы заставить потоки ждать. Этот код, похоже, работает как print threading.enumerate() показывает только основной поток до завершения скрипта при отладке. Просто чтобы убедиться, мне было интересно, если есть какой-либо вид проницательности для этого очистить реализации, что я, возможно, отсутствует, хотя это, кажется, работает для меня:
def signal_handler(signal, frame):
global kill_received
kill_received = True
msg = (
"\n\nYou pressed Ctrl+C!"
"\nYour logs and their locations are:"
"\n{}\n{}\n{}\n\n".format(debug, error, info))
logger.info(msg)
threads = threading.Event()
threads.clear()
while True:
time.sleep(3)
threads_remaining = len(threading.enumerate())
print threads_remaining
if threads_remaining == 1:
sys.exit()
def do_the_uploads(file_list, file_quantity,
retry_list, authenticate):
"""The uploading engine"""
value = raw_input(
"\nPlease enter how many concurent "
"uploads you want at one time(example: 200)> ")
value = int(value)
logger.info('{} concurent uploads will be used.'.format(value))
confirm = raw_input(
"\nProceed to upload files? Enter [Y/y] for yes: ").upper()
if confirm == "Y":
kill_received = False
sys.stdout.write("\x1b[2J\x1b[H")
q = CustomQueue()
def worker():
global kill_received
while not kill_received:
item = q.get()
upload_file(item, file_quantity, retry_list, authenticate, q)
q.task_done()
for i in range(value):
t = Thread(target=worker)
t.setDaemon(True)
t.start()
for item in file_list:
q.put(item)
q.join()
print "Finished. Cleaning up processes...",
#Allowing the threads to cleanup
time.sleep(4)
def upload_file(file_obj, file_quantity, retry_list, authenticate, q):
"""Uploads a file. One file per it's own thread. No batch style. This way if one upload
fails no others are effected."""
absolute_path_filename, filename, dir_name, token, url = file_obj
url = url + dir_name + '/' + filename
try:
with open(absolute_path_filename) as f:
r = requests.put(url, data=f, headers=header_collection, timeout=20)
except requests.exceptions.ConnectionError as e:
pass
if src_md5 == r.headers['etag']:
file_quantity.deduct()