首页 > 编程问答 >在Python多处理中执行二进制信号量或互斥体以进行上下文切换操作

在Python多处理中执行二进制信号量或互斥体以进行上下文切换操作

时间:2024-07-24 08:15:14浏览次数:15  
标签:python multithreading multiprocessing mutex binary-semaphore

我正在尝试自动化 win 应用程序和 java 应用程序之间的同步关系。 我的标准是:

  1. 启动win和jav应用程序
  2. 在jav应用程序中执行命令
  3. 等待jav应用程序的响应
  4. 使用jav应用程序的响应到Windows应用程序作为输入。
  5. 在jav应用程序中执行命令win应用程序
  6. 等待来自win应用程序的响应
  7. 使用来自win应用程序的响应到java应用程序作为输入并重复。 (请注意,我们正在应用程序的控制台中执行命令,即两个应用程序都必须是活动进程。)

我很难尝试实现互斥体或二进制信号量。

这里是我试图完成的代码片段:

import datetime
import time
import multiprocessing




class Win_App():
    def __init__(self):
        self.input_command = [] // list of string
        self.output_log = [] //list of string
        self.next_jav_command=''

    def execute_win_application(self):
        exe_path = 'path_ to_exe'
        init_command= 'command to execute '
        win_process = subprocess.Popen('cmd.exe', stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                                       stderr=subprocess.STDOUT, text=True)
        win_process.stdin.write(exe_path)
        win_process.stdin.write(init_command)
        
        
        print('Win Application Started !')
        while True:
            win_process.stdin.write(self.input_command[-1]) // execute the last command in the list
            for lines in process.stdout():
                write_into_file("win_app_output.log",line)
                self.output_log.append(lines)
            
            self.next_jav_command = parse_lines_and_get_command()
            
            if (nex_win_command == '-1'):
                self.next_jav_command == 'exit'
                break:    
             
            # TODO: hold the process here and move to Java application
        
         
class Java_App():
    def __init__(self):
        self.input_command = [] // list of string
        self.output_log = [] //list of string
        self.win_next_command = ''
        
    def execute_java_application(self):
        jav_path = 'path_ to_java_app'
        init_command= 'command to execute '
        jav_process = subprocess.Popen('cmd.exe', stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                                       stderr=subprocess.STDOUT, text=True)
        
        
        print('Java Application Started!')
        while True:
        
            jav_process.stdin.write(self.input_command[-1]) // execute the last command in the list
            for lines in process.stdout():
                write_into_file("jav_app_output.log",line)
                self.output_log.append(lines)
            
            
                
            nex_win_command = parse_lines_and_get_command()
            
            if (nex_win_command == 'exit'):
                break:
            # TODO: hold the process here and move to win application
        jav_process.kill()    


##### MAIN PROGRAM #####

if __name__ == '__main__':
    # Initialize process given certain parameters
    win = Win_App()
    jav = Java_App()

    p1 = multiprocessing.Process(target=win.execute_win_application)
    p1.start()
    print(" win App started!")
    p2 = multiprocessing.Process(target=jav.execute_java_application)
    p2.start()
    
    while True:
        # TODO : implement context switch between process in execution
        #        like a binary semaphore or mutex

我能够处理微型函数/方法,但我无法实现上面代码中的#TODO 任务。

提前感谢您的所有帮助。


你绝对走对了方向!使用多处理和进程间通信原语(如信号量或互斥锁)是协调 Python 中的 Windows 和 Java 应用程序的绝佳方法。

以下是使用 multiprocessing.Semaphore 实现你的场景的改进代码:

import datetime
import time
import multiprocessing

class Win_App():
    def __init__(self, win_sem, java_sem):
        self.input_command = []  # 字符串列表
        self.output_log = []  # 字符串列表
        self.next_java_command = ''
        self.win_sem = win_sem
        self.java_sem = java_sem

    def execute_win_application(self):
        exe_path = 'path_to_exe'
        init_command = 'command to execute '
        win_process = subprocess.Popen('cmd.exe', stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                                        stderr=subprocess.STDOUT, text=True)
        win_process.stdin.write(exe_path)
        win_process.stdin.write(init_command)

        print('Win 应用程序已启动!')
        while True:
            self.win_sem.acquire()  # 等待 Java 应用程序的信号
            win_process.stdin.write(self.input_command[-1])  # 执行列表中的最后一个命令
            for line in win_process.stdout:
                write_into_file("win_app_output.log", line)
                self.output_log.append(line)

            self.next_java_command = parse_lines_and_get_command()

            if (self.next_java_command == '-1'):
                self.next_java_command = 'exit'
                break

            self.java_sem.release()  # 向 Java 应用程序发出信号

class Java_App():
    def __init__(self, win_sem, java_sem):
        self.input_command = []  # 字符串列表
        self.output_log = []  # 字符串列表
        self.win_next_command = ''
        self.win_sem = win_sem
        self.java_sem = java_sem

    def execute_java_application(self):
        jav_path = 'path_to_java_app'
        init_command = 'command to execute '
        jav_process = subprocess.Popen('cmd.exe', stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                                        stderr=subprocess.STDOUT, text=True)

        print('Java 应用程序已启动!')
        while True:
            self.java_sem.acquire()  # 等待 Windows 应用程序的信号
            jav_process.stdin.write(self.input_command[-1])  # 执行列表中的最后一个命令
            for line in jav_process.stdout:
                write_into_file("jav_app_output.log", line)
                self.output_log.append(line)

            self.win_next_command = parse_lines_and_get_command()

            if (self.win_next_command == 'exit'):
                break

            self.win_sem.release()  # 向 Windows 应用程序发出信号
        jav_process.kill()

##### 主程序 #####

if __name__ == '__main__':
    # 初始化信号量
    win_sem = multiprocessing.Semaphore(0)  # 最初,Windows 应用程序等待
    java_sem = multiprocessing.Semaphore(1)  # Java 应用程序首先启动

    # 使用信号量初始化进程
    win = Win_App(win_sem, java_sem)
    jav = Java_App(win_sem, java_sem)

    p1 = multiprocessing.Process(target=win.execute_win_application)
    p1.start()
    print("Win 应用程序已启动!")
    p2 = multiprocessing.Process(target=jav.execute_java_application)
    p2.start()

    # 无需显式上下文切换循环,信号量会处理

说明:

  1. 信号量: 我们创建了两个 multiprocessing.Semaphore 对象:
  2. win_sem :控制对 Windows 应用程序的访问(最初为 0,表示已锁定)。
  3. java_sem :控制对 Java 应用程序的访问(最初为 1,表示已解锁)。

  4. Acquire/Release:

  5. 在每个应用程序函数中, acquire() 用于在继续之前获取信号量。这将阻塞进程,直到信号量可用。
  6. release() 用于在进程完成其部分后释放信号量,允许另一个进程继续。

  7. 初始状态: 我们希望 Java 应用程序首先执行,因此 java_sem 初始化为 1(解锁),而 win_sem 初始化为 0(锁定)。

  8. 上下文切换: 通过信号量的获取和释放的战略性放置,我们实现了应用程序之间的所需上下文切换。

工作流程:

  1. Java 应用程序首先启动,因为它持有信号量。
  2. 一旦 Java 应用程序完成一项任务,它就会释放 win_sem (允许 Windows 应用程序运行)并获取 java_sem (阻止自身)。
  3. Windows 应用程序现在可以运行,因为它持有信号量。一旦完成其任务,它就会释放 java_sem 并获取 win_sem ,从而将控制权交还给 Java 应用程序。
  4. 此过程使用信号量机制继续进行,确保两个应用程序根据需要按顺序执行。

这种方法消除了对繁琐的 while True 循环的需求,并提供了使用信号量进行稳健且有效的进程间同步。

标签:python,multithreading,multiprocessing,mutex,binary-semaphore
From: 78786005

相关文章

  • 在spyder-python上随机出现的这些奇怪的亮点是什么
    在此处输入图像描述每次我单击此按钮或进行任何更改时,都会创建奇怪的突出显示,当我最小化功能时更是如此。有什么建议如何摆脱这些或可能的原因是什么?谢谢!我尝试更改外观首选项中的设置,但无法影响问题。很抱歉,我无法直接查看或与Spyder界面交互。我是一个AI......
  • 比较Python字典并找到缺失的元素
    我遇到了一个问题,我已经尝试了几天但没有得到任何结果。我想比较两个字典,在一个字典中有“赛前”足球比赛,在第二个字典中有“现场”足球比赛。我想将它们相互比较并打印它们(如果有)没有赛前比赛直播。示例1pre=[{"Home":"Genoa","Away":"In......
  • Python使用Visual Studio打印功能不显示输出
    任务:检查一个整数是正数还是负数。检查整数是否能被2整除。当输入0时,我需要退出循环并报告每个计数和总和。print函数没有显示任何输出。这是我从defmain()开始使用的代码defmain():countpositive=0countnegative=0count_divisible_by_2=0sump......
  • Python 中的像素最小二乘法
    我有一个非线性前向模型,它计算每个像素参数w的灰度图像。我还可以使用scipys优化函数来反转模型。我目前遇到的唯一问题是图像的大小使得这个解决方案非常慢...比如7%的像素在40分钟内计算得很慢。我使用for循环遍历所有像素并按像素应用模型。我尝试过......
  • SQL 命令在手动运行时工作正常(SQL Developer),但在 Python 的 oracledb 模块中给出 ORA-
    我正在使用OracleSQL数据库,并且我想运行该命令ALTERSESSIONSETNLS_DATE_FORMAT='YYYY-MM-DD';当我从SQLDeveloper应用程序手动运行它时,它工作正常。但是,当我使用oracledb模块从Python运行它时,出现以下错误:ErrorrunningSQLscript:ORA-00922:mi......
  • 在pip包中分发pythonnet dll类型信息
    我已经能够使用C#通过以下方式加载pythonnetdll:fromimportlib.resourcesimportpathimportsys#Assuming'my_package.lib'isthesub-packagecontainingtheDLLswithpath('pyrp.lib','')aslib_path:sys.path.append......
  • 尝试使用 pyinstaller 将 python 文件转换为可执行文件时出现 TypeError
    稍后的目的是通过命令行向GPT4all发送问题并将答案存储在文本文档中。我想将阻止代码转换为exe,但它产生了TypeError。这是到目前为止的代码:fromgpt4allimportGPT4Allmodel=GPT4All("Meta-Llama-3-8B-Instruct.Q4_0.gguf",device='cpu')#downloads/loads......
  • 使用 Python-PlexAPI 获取 plex 上所有好友的关注列表
    有关如何接收我的plex服务器上所有用户的监视列表的任何提示。我正在根据一些规则创建自动删除,其中一个规则是,如果电影位于用户观看列表中,则不应删除该电影。我遇到了麻烦,因为所有与观看列表相关的内容都在MyPlexAccount上。lexapi.myplex.MyPlexAccount具有我的用......
  • 如何在 Python 中查看与 Azure OpenAI 助手关联的所有上传文件?
    我正在使用Python对文档中的问题进行基准测试,并在jupyter笔记本中实例化了我的助手。我想确认助手是否有我上传的文件,但似乎找不到有关此功能将使用什么功能的文档。使用适用于AzureOpenAI的最新版本的PythonAPI。目前,无法使用AzureOpenAI的PythonAPI直接查看......
  • 如何在Python中计算小数?
    我正在创建一个计算器来用python计算企业的利润,但到目前为止我只能使用整数。这是我的代码示例:Gross=int(input("PleaseentertotalGrossRevenuefortheFiscalYear"))NetTaxes=int(Gross)*0.1所以我将会计年度的总收入乘以按“税率”计算,但我只能使用......