Как убить объект запроса запросов, который находится в процессе

Изменить: основная часть этого вопроса до этой версии/обновления заключалась в том, как завершить QThread. Это было решено, вопрос пересматривается на Как убить объект остатка запросов, который находится в процессе.

http://docs.python-requests.org/en/v0.10.4/user/advanced/#asynchronous-requests Появляется с использованием неподвижных блоков асинхронного запроса — пользователь не может отменить публикацию, пока она выполняется.

По сути, это необходимая функциональность: когда пользователь нажимает Остановить загрузку, загрузка должна немедленно прекратиться, я могу остановить поток, используя stop(), однако он проверяется только после того, как цикл завершится. снова зациклился.

Таким образом, в принципе должна быть возможность использовать асинхронный запрос, который позволил бы мне проверить, следует ли отменить его во время запроса, однако я не знаю, как это сделать.

Какие-либо предложения? Предыдущая часть поста по-прежнему актуальна, поэтому ниже.
Обратите внимание, что первоначальный вопрос о том, как завершить QThread, был решен, и поэтому приведенный ниже код не слишком важен, он просто для контекста, сейчас мне нужна помощь в том, что я только что описал.




Я пишу программу, это загрузчик фотографий, я создал тему, в которой я загружаю файлы. Не могу понять как выйти из темы. Я пробовал предложения, которые я прочитал здесь:

1) Я пробовал логический флаг, обертывая его как вокруг метода, так и оператора for, который выполняет эту работу.

2) Я использовал «с», а затем попытался установить исключение.

Я хочу иметь возможность отменить загрузку, желательно быстро. Я много читал о том, что всегда рекомендуется «очистить» поток перед его завершением, я, честно говоря, не знаю, что означает «очистить его». Но я думаю, что у меня должна быть возможность просто убить поток, поскольку все, что он делает, это отправляет двоичные данные изображения в API TUMBLR. Не имеет значения, если запрос будет отменен раньше, потому что он просто отменит загрузку и в API.

В любом случае, вот моя тема:

class WorkThread(QtCore.QThread):
    def __init__(self):
        QtCore.QThread.__init__(self)
        global w
        w = WorkThread
    def __del__(slf):
        self.wait()        
    def run(self):
        url = 'https://www.tumblr.com/api/write'
        files = os.listdir(directory)
        for file in files:
            file_path = os.path.join(directory + '\\' + file)
            file_path = str(file_path)
            if file_path[-3:] in ['bmp', 'gif', 'jpg', 'png', 'thm', 'tif', 'yuv']:
                self.emit(QtCore.SIGNAL('update(QString)'), "Uploading %s ..." % file_path)
                print smart_str(password)
                data = {'email': email, 'password': password, 'type': 'photo'}
                with open(file_path, 'rb') as photo:
                    r = requests.post(url, data=data, files={'data': photo})
                print r.content
        self.emit(QtCore.SIGNAL('update(QString)'), 'All finished! Go check out your stuff on tumblr :)\n')
        return

Вот как я это называю.

def upload(self):
    self.doneBox.clear()

    self.workThread = WorkThread()
    self.connect( self.workThread, QtCore.SIGNAL("update(QString)"), self.startUploading )
    self.workThread.start()

Может ли кто-нибудь предложить способ, которым я могу быстро и тихо завершить поток? ИЛИ, если вы считаете, что это нехорошо, способ безопасно остановить это.

ОДНАКО, если я не убью его мгновенно, и он снова пройдет цикл for в методе run(), он загрузит фотографию, которую загружал, КОГДА пользователь нажимает «Остановить загрузку». Я бы не хотел, чтобы он это делал, я бы предпочел, чтобы он прекратил загрузку текущей фотографии, как только пользователь нажмет "Остановить загрузку".

Спасибо.


person Anteara    schedule 22.02.2012    source источник


Ответы (2)


Я не знаю, что вы делаете с этим global w; w = WorkThread, но это кажется бессмысленным, поскольку вы ничего с ним не делаете.

В вашем __init__() вам нужен флаг:

def __init__(self):
    ...
    self._isRunning = False

В вашем методе run() вы просто проверяете этот флаг и выходите при необходимости:

def run(self):
    self._isRunning = True
    while True:
        if not self._isRunning:
            # clean up or close anything here
            return
        # do rest of work

И, возможно, добавить простой метод удобства:

def stop(self):
    self._isRunning = False
    self.wait()

Когда в документации упоминается очистка, они говорят о закрытии ресурсов, которые вы, возможно, открыли, отмене действий, которые могли быть частично запущены, или о чем-то еще, что вы можете сигнализировать или обработать, прежде чем просто закрыть поток. объект. В случае вашего загрузчика вы хотите проверить, должен ли поток завершаться, прежде чем запускать каждый процесс загрузки. Это даст вам возможность остановить поток и завершить его работу до того, как он продолжит работу.

person jdi    schedule 22.02.2012
comment
Argh, я не понимаю, я добавил этот оператор while и if в метод run(), плюс я сказал ему напечатать «срабатывает», если должен произойти оператор if not, но этого не происходит. pastebin.com/05pSxCjG вот его пастебин, и я все еще называю его так же. Вот как я вызываю stop(). def stopUploading(self): self.workThread = WorkThread() self.workThread.stop() Можете ли вы указать причину, по которой это не работает? - person Anteara; 22.02.2012
comment
Это то, что вы вызываете из основного потока, который запускает workThread? В вашем примере pastebin вы только проверяете, должен ли поток выйти один раз, прежде чем он зациклится на файловой системе. Затем, как только это будет сделано со всем каталогом, он начнет сначала и проверит, должен ли он выйти, а затем снова зациклится на каталоге. Это тот функционал, который вам нужен? Если все, что вам нужно, это один раз перебрать каталог, избавьтесь от while и просто выполняйте for file in files с проверкой self._isRunning каждый раз. Если это все еще сбивает вас с толку, то, может быть, нам стоит поговорить? - person jdi; 22.02.2012
comment
В принципе, я не могу заставить его работать, я думаю, что разговор был бы хорошим. - person Anteara; 24.02.2012
comment
Мы можем продолжить это в чате: chat.stackoverflow.com/rooms/8184/terminate-qthread-python -pyqt - person jdi; 24.02.2012
comment
Похоже, у меня недостаточно репутации, чтобы говорить в разговоре, и я живу в Австралии, поэтому наши часовые пояса действительно не складываются, я посмотрю на пример, который вы написали. Редактировать: теперь я могу получить доступ к разговору. - person Anteara; 25.02.2012

Попробуйте завершить его:

self.workThread.terminate()

Только будьте осторожны при этом. Поскольку вы выполняете сетевую операцию, вы не можете ее остановить, но обычно делаете так:

# Logic...

if self.running:
  # Continue logic...

Вы устанавливаете self.running вне потока.

person Blender    schedule 22.02.2012