- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
使用 Linux 和 Python 2.7.6,我有一个脚本可以一次上传大量文件。我在队列和线程模块中使用多线程。
我为 SIGINT 实现了一个处理程序,以便在用户按下 ctrl-C 时停止脚本。我更喜欢使用守护线程,这样我就不必清除队列,这需要大量重写代码才能使 SIGINT 处理程序能够访问 Queue 对象,因为处理程序不接受参数。
为了确保守护线程在 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()
最佳答案
如果你想处理Ctrl+C
;在主线程中处理 KeyboardInterrupt
异常就足够了。不要在函数中使用 global X
除非你在其中执行 X = some_value
。使用 time.sleep(4)
允许线程清理是一种代码味道。你不需要它。
I am using threading.Event() and threading.clear() to make threads wait.
此代码对您的线程没有影响:
# create local variable
threads = threading.Event()
# clear internal flag in it (that is returned by .is_set/.wait methods)
threads.clear()
不要从多线程程序中的信号处理程序调用 logger.info()
。它可能会使您的程序陷入僵局。信号处理程序只能调用一组有限的函数。安全的选择是在其中设置一个全局标志并退出:
def signal_handler(signal, frame):
global kill_received
kill_received = True
# return (no more code)
信号可能会延迟到 q.join()
返回。即使信号立即发出; q.get()
阻塞你的子线程。它们挂起直到主线程退出。要解决这两个问题,您可以使用 sentinel 向子进程发出没有更多工作的信号,在这种情况下完全放弃信号处理程序:
def worker(stopped, queue, *args):
for item in iter(queue.get, None): # iterate until queue.get() returns None
if not stopped.is_set(): # a simple global flag would also work here
upload_file(item, *args)
else:
break # exit prematurely
# do child specific clean up here
# start threads
q = Queue.Queue()
stopped = threading.Event() # set when threads should exit prematurely
threads = set()
for _ in range(number_of_threads):
t = Thread(target=worker, args=(stopped, q)+other_args)
threads.add(t)
t.daemon = True
t.start()
# provide work
for item in file_list:
q.put(item)
for _ in threads:
q.put(None) # put sentinel to signal the end
while threads: # until there are alive child threads
try:
for t in threads:
t.join(.3) # use a timeout to get KeyboardInterrupt sooner
if not t.is_alive():
threads.remove(t) # remove dead
break
except (KeyboardInterrupt, SystemExit):
print("got Ctrl+C (SIGINT) or exit() is called")
stopped.set() # signal threads to exit gracefully
我已将 value
重命名为 number_of_threads
。我使用了显式线程集
如果一个单独的 upload_file()
block ,那么程序将不会在 Ctrl-C
上退出。
对于 multiprocessing.Pool
接口(interface),您的案例似乎足够简单:
from multiprocessing.pool import ThreadPool
from functools import partial
def do_uploads(number_of_threads, file_list, **kwargs_for_upload_file):
process_file = partial(upload_file, **kwargs_for_upload_file)
pool = ThreadPool(number_of_threads) # number of concurrent uploads
try:
for _ in pool.imap_unordered(process_file, file_list):
pass # you could report progress here
finally:
pool.close() # no more additional work
pool.join() # wait until current work is done
它应该在 Ctrl-C
上正常退出,即,允许完成正在进行的上传,但不会开始新的上传。
关于突然 sys.exit() 上的 Python 守护进程线程清理逻辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20318859/
我相信所有这些(甚至是 die() 或 die(0))都是相同的。如果它们不相同,那么哪个更适合成功退出脚本?如果它们相同,是否有任何首选标准表明脚本成功完成?我倾向于使用 exit;. 编辑:所有答
我想知道Java中以下之间的区别 System.exit(0);System.exit(-1);System.exit(1); 我什么时候必须适本地使用上面的代码?
我注意到 Powershell 中有一个奇怪的行为。有两个 .ps1 文件: main.ps1: echo "running exit.ps1" $myexitcode = & ".\exit.p
Anylogic Process Modeling Library 中很少有像“Source”这样的 block 具有“On exit”和“On at exit”这样的操作。两者有什么区别? 我试图创
所以我有这个 Bash 脚本: #!/bin/bash PID=`ps -u ...` if [ "$PID" = "" ]; then echo $(date) Server off: no
(gdb) info symbol exit exit in section .text of /lib64/libc.so.6 (gdb) info symbol _exit _exit in se
如果我想启动一个简单的应用程序,几周前我使用它没有出现错误,我会收到错误消息。那是他的错误描述: Launching lib\main.dart on SM J530F in debug mode..
这个问题已经有答案了: Using Platform.exit() and System.exit(int) together (3 个回答) 已关闭 5 年前。 这里有人建议使用后者。我是java新
我的理解是,在 bash 中,一个普通的 exit 将完成一个具有最后一个命令的退出状态的脚本。但我也看到有人使用 exit $? 并且当我建议它具有相同的行为时被质疑。 这两个脚本之间有什么有意义的
我看到一些代码是这样做的: if(something){ echo 'exit from program'; die; } ...more code 和其他只使用 die 的人: if
exit和exit有什么区别!在 ruby 中? 最佳答案 一些事情: 退出处理程序以“退出”形式而非“退出!”形式运行。这意味着分配给“清理”的任何代码都不会使用“退出!”运行 “退出状态”在“退出
我们有一堆 .bat构建脚本由基于 PowerShell 的 GitLab 运行程序调用,这些脚本最近从以下内容重构: program args if !errorlevel! neq 0 exit
我想关闭具有指定返回码的 javafx 应用程序。浏览 SO 上的答案,我发现了以下成语: Platform.exit(); System.exit(0); 例如这里: Stop threads be
exit 和 C++ 中的 std::exit 有什么区别?我已经对其进行了研究,但我找不到任何东西。 这两个代码有什么区别: 1: if(SDL_Init(SDL_INIT_EVERYTHING)
我需要一个替代方法来在线程函数内终止 python 脚本。我的意图是在客户端输入 0 时终止服务器...这是否不起作用,因为线程尚未终止?这是我的代码: socket = socket.socket(
我想在崩溃后重新启动应用程序。我正在使用下面的代码来执行该任务。 Intent mStartActivity = new Intent(HomeActivity.this, SplashScreen
在Delphi中,你可以退出一个函数并给它一个返回值,这与C/C++/Java/C#等中的return关键字非常相似 Exit(1); 但是,我通常会写这样的内容: Result := 1; Exit
我想知道是否有任何方法可以处理浏览器退出事件。 例如,我想在用户单击交叉退出或关闭浏览器时发送查询。 最佳答案 我想我已经找到了解决办法。我没有在 IE 上测试过它,但它似乎在 Firefox 上运行
我在 Archlinux 的 mkinitcpio 脚本中找到了以下代码片段。 cleanup() { if [[ $workdir ]]; then # when PRESE
我使用以下代码计算数据帧所有行之间的余弦相似度: from pyspark.ml.feature import Normalizer from pyspark.mllib.linalg.distrib
我是一名优秀的程序员,十分优秀!