【发布时间】:2020-03-19 16:34:40
【问题描述】:
搜索了这个,但似乎找不到已经问过的人,所以就这样吧。
我开始切换到 IPython 作为 Windows 7 上的首选 shell,我想对其进行配置,以便将命令传递给系统 shell 的 bang magic (!cmd) 使用 PowerShell而不是 cmd.exe,这样我就可以利用 MS 所做的增强,但不必将我的 %COMSPEC% 更改为 PowerShell(我的公司仍然使用几个基于 CMD 的 .BAT 来实现自动化,我不想要打破那些)。
我会将我的问题发布在顶部,因为答案可能不需要以下任何信息:
- 我错过了什么吗?有没有办法在 IPython 中使用配置文件来指定系统命令解释器?
- 如果 !1,我是否缺少从 PowerShell 中使用该进程本地的机器范围环境变量启动子进程的方法?
调查/测试
查看 IPython 代码,我看到它使用 os.system() 将命令发送到 shell,而不是 subprocess.call()。这让事情变得有些复杂,因为 os.system* 只使用 COMSPEC,而使用 subprocess*,您可以指定要使用的可执行文件。
我尝试加载 PowerShell,设置 $env:comspec 变量,然后从该 shell 中启动 IPython,但即使 COMSPEC 似乎已设置,即使在 IPython 中,它看起来仍然在使用 CMD:
[PS] C:\> $env:comspec
C:\Windows\system32\cmd.exe
[PS] C:\> $env:comspec = 'powershell.exe'
[PS] C:\> $env:comspec
powershell.exe
[PS] C:\> & 'C:\Python33\Scripts\ipython3.exe'
Python 3.3.2 (v3.3.2:d047928ae3f6, May 16 2013, 00:03:43) [MSC v.1600 32 bit (Intel)]
Type "copyright", "credits" or "license" for more information.
IPython 1.1.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: import os; os.getenv('comspec')
Out[1]: 'powershell.exe'
In [2]: !gci
'gci' is not recognized as an internal or external command,
operable program or batch file.
In [3]: os.system('gci')
'gci' is not recognized as an internal or external command,
operable program or batch file.
Out[3]: 1
看起来本地修改的 COMSPEC 正在传递给 IPython(作为进行本地更改的 PowerShell 进程的子进程),但 os.system 看起来仍在使用持久设置。
我尝试了类似的方法,使用[Environment]::SetEnvironmentVariable("ComSpec", 'powershell.exe', [System.EnvironmentVariableTarget]::User),以防我只更改用户范围的环境变量就可以逃脱,但这也不起作用(与上面相同的结果 - os.getenv('ComSpec') 显示 powershell,但是!-ed 命令发送到 CMD)。
由于前面提到的原因,更改机器范围的环境变量似乎符合我的要求,但对我来说不是一个有效的解决方案。
[PS] C:\> $env:comspec
C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe
[PS] C:\> [Environment]::GetEnvironmentVariable('ComSpec','User')
[PS] C:\> [Environment]::GetEnvironmentVariable('ComSpec','Machine')
C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe
[PS] C:\> & 'C:\Python33\Scripts\ipython3.exe'
Python 3.3.2 (v3.3.2:d047928ae3f6, May 16 2013, 00:03:43) [MSC v.1600 32 bit (Intel)]
Type "copyright", "credits" or "license" for more information.
IPython 1.1.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: !gci env:ComSpec
Name Value
---- -----
ComSpec C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe
由于这不是一个可行的持续解决方案,我通过修改 ConEmu* 中的设置进行了更多测试。通过在 Settings > Startup 中设置 Explicit executable 和 Set ComSpec environment variable for child processes to selected value* 标志,我能够在不更改全局变量的情况下做到这一点> ComSpec,并提供 powershell.exe 的路径,但我不确定这是否会对使用 ConEmu 打开的 CMD 控制台产生负面影响,因为该设置是全局的(在 ConEmu 内)。这就是导致我问上面的问题 2 的原因,因为我不确定如何在 PowerShell 中设置进程/子本地、机器范围的环境变量(如果这样的事情甚至可能的话)。
最后,我的梦想目标是让 IPython 通过配置文件支持命令外壳解释器的规范,但要做到这一点,os.system() 不能成为使用的东西。我打算在我的本地副本(a'la this Python Doc)中修补用subprocess.call() 替换它来测试,但如果有人已经玩过它,或者当前模型是否有足够的优势而不是使用@ 987654335@ 我不知道,我很高兴听到它。看起来这已经在非 Windows 系统 (GitHub) 上完成了,但我对这种规模的 Python 还是很陌生,我不能肯定地说,如果在Windows 端的条件也是如此。
脚注
啊!显然,必须拥有 10 多个声誉才能正确记录问题。以下是我不允许在上面发布的链接:
- os.system - docs.python.org/3.3/library/os.html#os.system
- 子进程 - docs.python.org/3.3/library/subprocess.html
- ConEmu - code.google.com/p/conemu-maximus5/
【问题讨论】:
-
如果您也想为在 Windows 上使用
subprocess做出贡献,我们当然会考虑。我认为它尚未更改的主要原因是我们没有很多 Windows 用户来测试更改。 -
@ThomasK - 酷。不想继续做这样的改变,却发现使用
os.system()是一个经过深思熟虑的选择,并且会留下来。
标签: windows powershell ipython