search了这个,似乎无法find任何人已经问过,所以在这里。
我开始切换到IPython作为我在Windows 7上的shell,并且我想configuration它,以便将命令传递给系统shell的bang magic( !cmd
)使用PowerShell而不是cmd。 exe,这样我就可以利用MS所做的改进,而无需将我的%COMSPEC%
更改为PowerShell(我的公司仍然使用多个基于CMD的.BAT进行自动化,我不想破坏这些) 。
我会在上面发表我的问题,因为答案可能不需要下面的任何信息:
查看IPython代码,我发现它使用os.system()
将命令发送到shell,而不是subprocess.call()
。 这使得事情变得更加复杂一些,因为os.system *只是使用COMSPEC,其中subprocess*可以指定要使用的可执行文件。
我尝试了加载PowerShell,设置$env:comspec
variables,然后从该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进程的一个subprocess,使本地更改),但os.system
看起来仍然使用持久化设置。
我尝试了一些类似的东西,使用[Environment]::SetEnvironmentVariable("ComSpec", 'powershell.exe', [System.EnvironmentVariableTarget]::User)
,以防万一我只能改变用户范围的环境variables没有工作,或者(与上面相同的结果 – os.getenv('ComSpec')
显示os.getenv('ComSpec')
,但!命令被发送到CMD)。
改变机器范围的环境variables似乎做我想要的,但不是一个有效的解决scheme,因为我之前提到的原因。
[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
由于这不是一个可行的解决scheme,所以我通过修改ConEmu *中的设置来testing更多。 我能够做到这一点,而无需更改全局variables通过将subprocess的显式可执行文件和Set ComSpec环境variables设置为 设置>启动> ComSpec中 选定的值 *标志,并提供powershell.exe的path,但我不肯定这样做是否会对使用ConEmu打开的CMD控制台产生负面影响,因为该设置是全球性的(在ConEmu内)。 因为我不确定如何在PowerShell中设置进程/子本地,机器范围的环境variables(如果这样的话甚至是可能的话),所以这就是我提出的问题2的问题。
最后,我的梦想目标是让IPython通过configuration文件来支持命令解释器的规范,但为此, os.system()
不能被使用。 我打算用我的本地副本(a'la this Python Doc )中的subprocess.call subprocess.call()
replace它来testing,但是如果任何人已经玩过了,或者如果当前模型有足够的优势来使用我不知道的subprocess
,我很乐意听到它。 看起来这已经在非Windows系统( GitHub )中完成了,但是在这个尺度上我已经足够新到了Python,我不能肯定地说如果在Windows端使用这个改变的条件,以及。
尔加! 必须要有10多个声誉才能正确logging问题,显然。 以下是我不能在上面发表的链接:
您可以使用IPython的脚本魔术来执行PowerShell命令。
在您的IPython配置文件中 ,修改ipython_config.py
以包含以下行:
c.ScriptMagics.script_magics = ['powershell'] c.ScriptMagics.script_paths = { 'powershell':'powershell.exe -noprofile -command -'}
-command -
告诉PowerShell执行标准输入文本作为命令。 如果您需要加载您的PS配置文件,您可以-noprofile
,但速度会更慢。
然后你可以使用%%powershell
作为脚本单元格的魔法 。
In [1]: %%powershell ...: 1..5 1 2 3 4 5
为了使它更容易使用,我定义了我自己的神奇函数来处理PowerShell命令,包括行和单元格的魔法。 (请参阅: 定义您自己的魔术 )可以通过将脚本放置在IPython配置文件的启动文件夹中来自动加载。 (即~\.ipython\profile_default\startup\05-powershell_magic.py
)
from IPython.core.magic import register_line_cell_magic from IPython import get_ipython ipython = get_ipython() @register_line_cell_magic def ps(line, cell=None): "Magic that works both as %ps and as %%ps" if cell is None: ipython.run_cell_magic('powershell', '--out posh_output' ,line) return posh_output.splitlines() else: return ipython.run_cell_magic('powershell', line, cell)
要使用%ps
行魔术并将输出返回到一个变量:
In [1]: ps_version = %ps $PSVersionTable.PSVersion.ToString() In [2]: print(ps_version) ['2.0']
要使用%%ps
单元格魔术并输出到控制台:
In [3]: %%ps ...: gci c:\ Directory: C:\ Mode LastWriteTime Length Name ---- ------------- ------ ---- dr-- 10/2/2013 10:39 AM Program Files dr-- 12/6/2013 1:44 PM Program Files (x86) d---- 2/6/2014 4:33 PM TEMP dr-- 11/27/2013 11:10 AM Users d---- 1/13/2014 11:21 AM Windows
单元格--out <variable name>
可以用--out <variable name>
发送输出到一个变量:
In [4]: %%ps --out process_name_id ...: $procs = gps| select Name, ID ...: $procs| ConvertTo-Csv -NoType| select -skip 1 In [5]: import csv In [6]: list(csv.reader(process_name_id.splitlines())) Out[6]: [['7+ Taskbar Numberer', '3400'], ['acrotray', '3668'], ['armsvc', '1772'], ['audiodg', '4160'], ['AutoHotkeyU64', '472'], ['chrome', '6276'], ...
这是一个有点狡猾,但你可以诉诸使用预制的PowerShell脚本
os.system('powershell C:\file.ps1')
或者像这样的单个命令:
os.system("powershell; gci | where {$_.Fullname -contains 'some stuff'}")
编辑:
我只是测试了这个,似乎只需要打开一个PowerShell实例:
os.system("powershell; gci; gc C:\windows\system32\drivers\etc\services; [system.net.dns]::gethostbyaddress('203.20.74.6') | more")
但是如果你不得不在脚本中多次调用这种类型的东西,我想它会变得丑陋和缓慢。