多处理时如何获取每个进程ID [英] How to get each Process ID when multiprocessing

查看:56
本文介绍了多处理时如何获取每个进程ID的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些问题,因为我是Python和Pyside的新手.

I have some problems because I'm newbie in Python and Pyside.

我有N个进程正在同时运行.

I have N processes which are running at the same time.

由于这些过程需要花费一些时间才能完成工作,因此最终用户可能希望取消特定的过程.因此,我需要一种方法来了解将此功能添加到程序中的进程的ID.

Since these processes take some times to finish their job, it's possible that end user wants to cancel a specific process. So I need a way to know the IDs of processes for adding this feature to the program.

Stackoverflow中有一个答案,这正是我正在做的事情.

There is an answer in Stackoverflow which is exactly what I'm doing.

这是代码:

#!/usr/bin/env python3
import multiprocessing, multiprocessing.pool, time, random, sys
from PySide.QtCore import *
from PySide.QtGui import *

def compute(num_row):
    print("worker started at %d" % num_row)
    random_number = random.randint(1, 10)
    for second in range(random_number):
        progress = float(second) / float(random_number) * 100
        compute.queue.put((num_row, progress,))
        time.sleep(1)
    compute.queue.put((num_row, 100))

def pool_init(queue):
    # see https://stackoverflow.com/a/3843313/852994
    compute.queue = queue

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.toolBar = self.addToolBar("Toolbar")
        self.toolBar.addAction(QAction('Add Task', self, triggered=self.addTask))
        self.table = QTableWidget()
        self.table.verticalHeader().hide()
        self.table.setColumnCount(2)
        self.setCentralWidget(self.table)

        # Pool of Background Processes
        self.queue = multiprocessing.Queue()
        self.pool = multiprocessing.Pool(processes=4, initializer=pool_init, initargs=(self.queue,))
        # Check for progress periodically
        self.timer = QTimer()
        self.timer.timeout.connect(self.updateProgress)
        self.timer.start(2000)

    def addTask(self):
        num_row = self.table.rowCount()
        self.pool.apply_async(func=compute, args=(num_row,))
        label = QLabel("Queued")
        bar = QProgressBar()
        bar.setValue(0)
        self.table.setRowCount(num_row + 1)
        self.table.setCellWidget(num_row, 0, label)
        self.table.setCellWidget(num_row, 1, bar)

    def updateProgress(self):
        if self.queue.empty(): return
        num_row, progress = self.queue.get() # unpack
        print("received progress of %s at %s" % (progress, num_row))
        label = self.table.cellWidget(num_row, 0)
        bar = self.table.cellWidget(num_row, 1)
        bar.setValue(progress)
        if progress == 100:
            label.setText('Finished')
        elif label.text() == 'Queued':
            label.setText('Downloading')
        self.updateProgress() # recursion

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())

我添加了一个停止"按钮,我知道如何获取表中的所选行,但是我不知道如何获取所选行的进程ID以终止.

I added an "stop" button, and I know how to get the selected row in the table, but I don't know how to get the process id of the selected row for terminating.

更新1 :

为了简化操作,我可以更改

for make this easier I can change

multiprocessing.Pool(processes=4, initializer=pool_init, initargs=(self.queue,))

multiprocessing.Pool(processes=1, initializer=pool_init, initargs=(self.queue,))

通过这种方式,所有进程都必须等到进程完成

in this way all processes have to wait till a process finish

现在我们有一个进程正在运行,而其他进程正在排队,如何获取正在运行的进程的进程ID?

now we have one process running and others are in queue,How I can get just the process id of that running process ?

推荐答案

我整理了一个演示,该演示或多或少地复制了多处理示例,并具有中止上传的功能.它一次只能处理六个并行的上载,因为这是QNetworkAccessManager所允许的最大数量.但是,可以通过简单地添加另一个QNetworkAccessManager来增加此限制.

I hacked together an demo that more or less reproduces the multiprocessing example, with the addition of the ability to abort uploads. It can only handle six parallel uploads at a time because that is the maximum QNetworkAccessManager will allow. However, this limit could be increased by simply adding another QNetworkAccessManager.

在测试演示时遇到一个问题.在某些情况下,后期数据似乎可以发送两次(请参见此处).但是我不知道这是Qt错误还是测试设置问题(我使用了python线程的httpserver).无论如何,通过在uploadProgress处理程序中关闭回复对象(参见下文),很容易修复.

There was one issue I came across while testing the demo. It seems that under some circumstances, the post-data can get sent twice (see here, for example). But I don't know whether this is a Qt bug, or an issue with my test setup (I used a python threaded httpserver). Anyway, it was easy enough to fix by closing the reply-object in the uploadProgress handler (see below).

from PyQt4 import QtCore, QtGui, QtNetwork

class Window(QtGui.QWidget):
    def __init__(self, address):
        QtGui.QWidget.__init__(self)
        self.address = address
        self.table = QtGui.QTableWidget(self)
        header = self.table.horizontalHeader()
        header.setStretchLastSection(True)
        header.hide()
        self.table.setColumnCount(2)
        self.button = QtGui.QPushButton('Add Upload', self)
        self.button.clicked.connect(self.handleAddUpload)
        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.table)
        layout.addWidget(self.button)
        self.netaccess = QtNetwork.QNetworkAccessManager(self)
        self._uploaders = {}

    def handleAddUpload(self):
        stream = QtCore.QFile('files/sample.tar.bz2')
        if stream.open(QtCore.QIODevice.ReadOnly):
            data = stream.readAll()
            stream.close()
            row = self.table.rowCount()
            button = QtGui.QPushButton('Abort', self.table)
            button.clicked.connect(lambda: self.handleAbort(row))
            progress = QtGui.QProgressBar(self.table)
            progress.setRange(0, len(data))
            self.table.setRowCount(row + 1)
            self.table.setCellWidget(row, 0, button)
            self.table.setCellWidget(row, 1, progress)
            uploader = self._uploaders[row] = Uploader(row, self.netaccess)
            uploader.uploadProgress.connect(self.handleUploadProgress)
            uploader.uploadFinished.connect(self.handleUploadFinished)
            uploader.upload(data, self.address)

    def handleUploadProgress(self, key, sent, total):
        print('upload(%d): %d [%d]' % (key, sent, total))
        progress = self.table.cellWidget(key, 1)
        progress.setValue(sent)

    def handleUploadFinished(self, key):
        print('upload(%d) finished' % key)
        button = self.table.cellWidget(key, 0)
        button.setDisabled(True)
        uploader = self._uploaders.pop(key)
        uploader.deleteLater()

    def handleAbort(self, key):
        try:
            self._uploaders[key].abort()
        except (KeyError, AttributeError):
            pass

class Uploader(QtCore.QObject):
    uploadProgress = QtCore.pyqtSignal(object, int, int)
    uploadFinished = QtCore.pyqtSignal(object)

    def __init__(self, key, parent):
        QtCore.QObject.__init__(self, parent)
        self._key = key
        self._reply = None

    def abort(self):
        if self._reply is not None:
            self._reply.abort()

    def upload(self, data, url):
        if self._reply is None:
            request = QtNetwork.QNetworkRequest(QtCore.QUrl(url))
            request.setHeader(
                QtNetwork.QNetworkRequest.ContentTypeHeader,
                'application/x-www-form-urlencoded')
            self._reply = self.parent().post(request, data)
            self._reply.uploadProgress.connect(self.handleUploadProgress)
            self._reply.finished.connect(self.handleFinished)

    def handleUploadProgress(self, sent, total):
        self.uploadProgress.emit(self._key, sent, total)
        if sent >= total:
            # prevent duplicated uploads
            self._reply.close()

    def handleFinished(self):
        self._reply.deleteLater()
        self._reply = None
        self.uploadFinished.emit(self._key)

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window('http://localhost:54321/upload')
    window.setGeometry(500, 300, 500, 300)
    window.show()
    sys.exit(app.exec_())

这篇关于多处理时如何获取每个进程ID的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆