线程化子进程并获取进度

2024-04-25 22:11:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我想稍微自动化一下手刹,并用python编写了一个小程序。 现在我有一个关于子进程和线程模块的问题。我想动态更改我运行的手刹进程的数量。我实现了队列模块,用于获取和放置电影。在

CompressThread调用handbrake类中的encode方法,并encode调用_execute。现在我想存储进度,我在手刹类,压缩机类集中读到的。所以我可以将进度发布到asocketserver和awebgui。不,我写一个sqlite3数据库,但这应该被删除(因为线程问题),并且只有在程序退出时保存。在

我认为集中保存数据的唯一方法是创建另一个线程,并轮询CompressThread类中的数据。我的问题是我的程序有4个线程。在

有更好的解决办法吗?也许数据库没有错,我不应该删除它?在

压缩机等级:

class CompressThread(threading.Thread):
    """ Manage the queue of movies to be compressed
    """

    def __init__(self):
        threading.Thread.__init__(self)
        self._config = ConfigParser()
        self._config.process_config()
        self._handbrake = self._config.get_handbrake()
        self._lock = threading.Lock()

    def run(self):
        while True:
            movie_id = QUEUE.get()
            return_code = self._handbrake.encode(movie_id)
            print(return_code)
            QUEUE.task_done()


class Compressor(object):
    """ Compresses given mkv file

    Attributes:


    """

    __MAX_THREADS = 1

    def __init__(self):
        self._dest_audio_tracks = None
        self._log = None
        self.settings = None
        self.config = ConfigParser()
        self._database = db.DB()
        self._database.connect()
        self._running = True
        self._threads = []
        try:
            self.handbrake, self._log = self.config.process_config()
            self._log = logging.getLogger("Compressor")
        except ConfigError as error:
            raise Error("Config error: {0}".format(error))

    def process_file(self, input_file, output_file, title):
        if not os.path.exists(input_file):
            self._log.warning("Input file not exists: {0}".format(input_file))
            print("Input file not found: {0}".format(input_file))
        else:
            media_info = mediainfo.Mediainfo.parse(input_file)
            movie_settings = settings.Settings(input_file, title, output_file)
            movie_settings.parse(media_info)
            self._log.info("Added file {0} to list".format(movie_settings.input_file))
            QUEUE.put(self._database.insert_movie(movie_settings))

            print("File added.")

    def start(self):
        self._threads = [CompressThread() for i in range(self.__MAX_THREADS)]
        for thread in self._threads:
            thread.setDaemon(True)
            thread.start()
        while self._running:
            cmd = input("mCompress> ")
            if cmd == "quit":
                self._running = False
            elif cmd == "status":
                print("{0}".format(self._threads))
            elif cmd == "newfile":
                input_file = input("mCompress> newFile> Input filename> ")
                output_file = input("mCompress> newFile> Output filename> ")
                title = input("mCompress> newFile> Title> ")
                self.process_file(input_file, output_file, title)

    def _initialize_logging(self, log_file):
        try:
            self._log_file = open(log_file, "a+")
        except IOError as error:
            log_error = "Could not open log file {0}".format(error)
            self._log.error(log_error)
            raise IOError(log_error)
        self._log_file.seek(0)

if __name__ == "__main__":
    options_parser = OptionsParser()
    args = options_parser.parser.parse_args()
    if args.start:
        Compressor().start()

手刹类的一部分:

^{2}$

Tags: selflogconfigformatinputsettingsdeferror
1条回答
网友
1楼 · 发布于 2024-04-25 22:11:51

做你计划做的事。在

如果这意味着你有5个线程而不是4个线程,那么呢?在

没有一个线程是CPU绑定的。也就是说,它们不是在处理数字、解析字符串或做其他计算工作,它们只是在等待I/O、外部进程或其他线程。因此,创建更多非CPU绑定的线程并没有什么坏处,除非你疯狂到你的操作系统不能再平稳地处理它们。有几百个。在

如果您的线程中有任何一个是CPU限制的,那么即使是2个也会太多。在CPython中,*线程必须获得全局解释器锁才能执行任何工作,**因此它们最终不会并行运行,并且在GIL上花费的时间比工作更多。但即便如此,添加另一个非CPU绑定线程,它将所有时间都花在等待CPU绑定线程正在填充的队列上,也不会使事情比现在更糟糕。***


至于数据库

只要有足够新的版本,SQLite3本身就可以进行多线程处理。但是Pythonsqlite3模块不是这样的,因为它与SQLite3引擎非常旧的版本向后兼容。有关详细信息,请参见文档中的Multithreading。如果我没有记错(站点似乎暂时关闭了,所以我无法检查),如果需要,您可以使用线程支持构建第三方模块^{}(stdlib模块基于它)。在

但是,如果您不是非常频繁地使用数据库,那么运行一个线程来与数据库对话,用一个队列来监听其他线程,是一个非常合理的设计。在


*和PyPy,但在其他实现中不一定。在

**扩展模块可以释放GIL以在C中工作,只要它们不接触Python中可见的任何值。一些著名的模块,如NumPy利用了这一点。在

***等待线程本身可能会受到CPU绑定线程的阻碍,尤其是在Python3.1及更早版本中,但它不会干扰它们。在

相关问题 更多 >