Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何";替换“`os.execvpe`在Windows上高效运行-如果;“儿童”;进程是一个交互式命令行应用程序?_Python_Windows_Subprocess_Spawn_Execvp - Fatal编程技术网

Python 如何";替换“`os.execvpe`在Windows上高效运行-如果;“儿童”;进程是一个交互式命令行应用程序?

Python 如何";替换“`os.execvpe`在Windows上高效运行-如果;“儿童”;进程是一个交互式命令行应用程序?,python,windows,subprocess,spawn,execvp,Python,Windows,Subprocess,Spawn,Execvp,我正在处理一个Python脚本,在做了一些准备工作之后,它会启动ssh。我的脚本实际上是一个小型CLI工具。在类Unix系统上,Python脚本在其生命周期结束时将自身替换为ssh客户端,因此用户现在可以直接与ssh交互(即在远程机器上运行任意命令等): os.execvpe('ssh',['ssh','-o','foo','user@host“],操作系统环境) 积极的惊喜和附带说明,以防您感到疑惑:Windows10实际上内置了OpenSSH的本机版本,因此在这个平台上有一个ssh命令 o

我正在处理一个Python脚本,在做了一些准备工作之后,它会启动
ssh
。我的脚本实际上是一个小型CLI工具。在类Unix系统上,Python脚本在其生命周期结束时将自身替换为
ssh
客户端,因此用户现在可以直接与
ssh
交互(即在远程机器上运行任意命令等):

os.execvpe('ssh',['ssh','-o','foo','user@host“],操作系统环境)
积极的惊喜和附带说明,以防您感到疑惑:Windows10实际上内置了OpenSSH的本机版本,因此在这个平台上有一个
ssh
命令

os.execvpe
存在于Windows上的Python标准库中,但它并不取代原始(Python)进程。情况是。。。有点复杂:。一句话:Windows没有实现相应的POSIX语义来替换正在运行的进程。

通常的做法是使用
subprocess.Popen
来代替,好的,有效地创建一个子进程。我可以启动子系统以便父系统继续运行,也可以在父系统死亡时启动子系统(我认为Windows确实支持后者,就像Unix系统一样)。无论哪种方式,用户都不能在命令行中与子级交互

假设我让父级保持活动状态,我现在必须编写大量代码,通过父级将用户I/O传递给子级或从子级传递给父级,例如。后者涉及到管理流,甚至线程,这取决于它的表现如何——很多地方可能会出现潜在问题和故障。我不喜欢这样做(如果我可以避免的话)

在所描述的场景中,如何在Windows上有效地替换
os.execvpe


编辑(1):可能与…相关的位和块

我想这取决于在将
STARTUPINFO
对象传递到
Popen
之前如何正确配置它。命令行实际上可以在Windows中继承


编辑(2):通过
pywin32
-
ssh
的部分解决方案将打开第二个新的
cmd
窗口,并可与之交互。Python的原始shell保持打开状态,Python本身退出:

从win32.Demos.winprocess导入进程
从shlex导入联接
进程(join(['ssh','-o',foo','user@host']))

您可以使用
subprocess.Popen
subprocess.call
函数代替
os.execvpe
。它们具有标志
shell
,确保子进程可以获得
stdin
。 我已在windows中尝试使用以下代码:

import os
import subprocess
subprocess.Popen('ssh -o foo user@host', shell=True, env=os.environ)

它是有效的。

A部分和不完整的解决方案如下所示,请参见《待办事项注释》

导入win32api、win32process、win32con
从shlex导入联接
si=win32process.STARTUPINFO()
#TODO修复标志
si.dwFlags=win32con.STARTF\u USESTDHANDLES^win32con.STARTF\u USESHOWWINDOW
#继承stdin、stdout和stderr
si.hStdInput=win32api.GetStdHandle(win32api.STD\u输入\u句柄)
si.hStdOutput=win32api.GetStdHandle(win32api.STD\u输出\u句柄)
si.hStdError=win32api.GetStdHandle(win32api.STD\u错误\u句柄)
#TODO固定值?
si.wShowWindow=1
#TODO设置值?
#si.dwX,si.dwY=。。。
#si.dwXSize,si.dwYSize=。。。
#si.lpDesktop=。。。
procArgs=(
无,#appName
加入(['ssh','-o',foo','user@host“]),#命令行
无,#进程属性
无,#线程属性
1、#bInheritHandles TODO?
win32process.CREATE_NEW_控制台,#dwCreationFlags
无,#新环境
无,#当前目录
是的#startupinfo
)
procHandles=win32process.CreateProcess(*procArgs)#运行。。。
ssh
打开第二个新的
cmd.exe
窗口,可以与之交互。包含Python的原始
cmd.exe
窗口保持打开状态,Python本身退出,将控制权返回到
cmd.exe
本身。它是可用的,尽管不一致且丑陋


我想这要归结为正确配置
win32process.STARTUPINFO
,但即使在阅读了大量关于它的文档之后,我还是无法理解它…

这显然不起作用。@s-m-e,你能详细说明一下吗,我想启动
ssh
,这样用户就可以交互使用它了。我的Python脚本在命令行中运行。
ssh
也是如此
ssh
应该从Python进程继承命令行,这样用户就可以实际与
ssh
交互。您的建议会启动
ssh
,但不会将控制权交给它。相反,它与我的Python脚本一起消失在后台。您可能想检查一下。@CristiFati在
expect
中包装
ssh
——这是“手动”传递所有用户I/O的一种变体。最后,它仍然相当复杂,但感谢您的想法。