我正在尝试自动化 win 应用程序和 java 应用程序之间的同步关系。 我的标准是:
- 启动win和jav应用程序
- 在jav应用程序中执行命令
- 等待jav应用程序的响应
- 使用jav应用程序的响应到Windows应用程序作为输入。
- 在jav应用程序中执行命令win应用程序
- 等待来自win应用程序的响应
- 使用来自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()
# 无需显式上下文切换循环,信号量会处理
说明:
-
信号量:
我们创建了两个
multiprocessing.Semaphore
对象: -
win_sem
:控制对 Windows 应用程序的访问(最初为 0,表示已锁定)。 -
java_sem
:控制对 Java 应用程序的访问(最初为 1,表示已解锁)。 -
Acquire/Release:
-
在每个应用程序函数中,
acquire()
用于在继续之前获取信号量。这将阻塞进程,直到信号量可用。 -
release()
用于在进程完成其部分后释放信号量,允许另一个进程继续。 -
初始状态: 我们希望 Java 应用程序首先执行,因此
java_sem
初始化为 1(解锁),而win_sem
初始化为 0(锁定)。 -
上下文切换: 通过信号量的获取和释放的战略性放置,我们实现了应用程序之间的所需上下文切换。
工作流程:
- Java 应用程序首先启动,因为它持有信号量。
-
一旦 Java 应用程序完成一项任务,它就会释放
win_sem
(允许 Windows 应用程序运行)并获取java_sem
(阻止自身)。 -
Windows 应用程序现在可以运行,因为它持有信号量。一旦完成其任务,它就会释放
java_sem
并获取win_sem
,从而将控制权交还给 Java 应用程序。 - 此过程使用信号量机制继续进行,确保两个应用程序根据需要按顺序执行。
这种方法消除了对繁琐的
while True
循环的需求,并提供了使用信号量进行稳健且有效的进程间同步。