Python - [Subprocess Popen Communicate] 在执行时挂起
Python - [Subprocess Popen Communicate] hangs on execution
我正在尝试 运行 一个简单的命令,该命令在执行我的自动化测试之前启动端口转发,但它每次都挂起。
最终目标是在会话结束时设置端口转发、获取 PID 并终止端口转发。
我在 macOS
并使用 Python 3.9.7
并尝试在 PyCharm IDE
.
中执行此操作
这是代码片段:
def setup_port_forward():
# command
command = 'kubectl port-forward api_service 8080:80 -n service_name'
# shell
shell_script = subprocess.Popen(command,
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
start_new_session=True)
# extract
try:
stdout, stderr = shell_script.communicate(timeout=15)
pid = int(stdout.decode().strip().split(' ')[-1])
except subprocess.TimeoutExpired:
shell_script.kill()
yield
# kill session
os.kill(pid, signal.SIGTERM)
我不会假装知道这是做什么的或它是如何工作的,因为我还在学习 python。
这是我看过的几个主题:
Python Script execute commands in Terminal
Python Script execute commands in Terminal
https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate
许多线程说在 shell 脚本中使用 subprocess.PIPE
可能会导致问题,但同样,在关于如何获取 PID 的不同线程上,使用的是这种方法。
我已经尝试使用不同主题中建议的不同方式:
command = 'kubectl port-forward api_service 8080:80 -n service_name'
# 1
os.system(command)
# 2
subprocess.Popen(command).communicate
# 3
subprocess.run(command)
# 4
subprocess.call(command)
# 5
commands.getstatusoutput(command)
他们都挂了。 运行 这是终端,工作正常。
这里的主要问题是 communicate
。你只想 Popen
这个过程,然后离开它 运行ning 直到你 kill
它。
你一定会尽可能避免 shell=True
;另见 Actual meaning of shell=True
in subprocess
我也没有看到 stdout
和 stderr
重定向有用。如果你只是想安静地 运行 它,可能只是重定向到 subprocess.DEVNULL
和从 subprocess.DEVNULL
重定向。
在这里创建一个单独的会话似乎很可疑;我也许也会放弃它。
Running Bash commands in Python 对在什么情况下首选哪种 subprocess
方法有一些指导。 TLDR 是 subprocess.run
对于您想要等待进程完成的情况,subprocess.Popen
当您不这样做时(但随后了解您在管理对象方面的职责)。
def setup_port_forward():
proc = subprocess.Popen(
['kubectl', 'port-forward', 'api_service', '8080:80', '-n', 'service_name'],
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
start_new_session=True)
yield
# When done
proc.kill()
这个函数作为生成器的设计也略显怪异;我可能会建议您改为 context manager。
我正在尝试 运行 一个简单的命令,该命令在执行我的自动化测试之前启动端口转发,但它每次都挂起。
最终目标是在会话结束时设置端口转发、获取 PID 并终止端口转发。
我在 macOS
并使用 Python 3.9.7
并尝试在 PyCharm IDE
.
这是代码片段:
def setup_port_forward():
# command
command = 'kubectl port-forward api_service 8080:80 -n service_name'
# shell
shell_script = subprocess.Popen(command,
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
start_new_session=True)
# extract
try:
stdout, stderr = shell_script.communicate(timeout=15)
pid = int(stdout.decode().strip().split(' ')[-1])
except subprocess.TimeoutExpired:
shell_script.kill()
yield
# kill session
os.kill(pid, signal.SIGTERM)
我不会假装知道这是做什么的或它是如何工作的,因为我还在学习 python。
这是我看过的几个主题:
Python Script execute commands in Terminal
Python Script execute commands in Terminal
https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate
许多线程说在 shell 脚本中使用 subprocess.PIPE
可能会导致问题,但同样,在关于如何获取 PID 的不同线程上,使用的是这种方法。
我已经尝试使用不同主题中建议的不同方式:
command = 'kubectl port-forward api_service 8080:80 -n service_name'
# 1
os.system(command)
# 2
subprocess.Popen(command).communicate
# 3
subprocess.run(command)
# 4
subprocess.call(command)
# 5
commands.getstatusoutput(command)
他们都挂了。 运行 这是终端,工作正常。
这里的主要问题是 communicate
。你只想 Popen
这个过程,然后离开它 运行ning 直到你 kill
它。
你一定会尽可能避免 shell=True
;另见 Actual meaning of shell=True
in subprocess
我也没有看到 stdout
和 stderr
重定向有用。如果你只是想安静地 运行 它,可能只是重定向到 subprocess.DEVNULL
和从 subprocess.DEVNULL
重定向。
在这里创建一个单独的会话似乎很可疑;我也许也会放弃它。
Running Bash commands in Python 对在什么情况下首选哪种 subprocess
方法有一些指导。 TLDR 是 subprocess.run
对于您想要等待进程完成的情况,subprocess.Popen
当您不这样做时(但随后了解您在管理对象方面的职责)。
def setup_port_forward():
proc = subprocess.Popen(
['kubectl', 'port-forward', 'api_service', '8080:80', '-n', 'service_name'],
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
start_new_session=True)
yield
# When done
proc.kill()
这个函数作为生成器的设计也略显怪异;我可能会建议您改为 context manager。