配置IPython以使用powershell而不是cmd

时间:2013-10-28 20:55:42

标签: windows powershell ipython

搜索了这个,似乎找不到任何已经问过的人,所以现在就去了。

我开始在Windows 7上切换到IPython作为我的首选shell,我想配置它以便将魔法(!cmd)传递给系统shell使用PowerShell而不是cmd.exe,这样我就可以利用MS所做的增强功能,但无需将%COMSPEC%更改为PowerShell(我的公司仍然使用几个基于CMD的.BAT进行自动化,而我不想打破那些)。

我会在顶部发布我的问题,因为答案可能不需要以下任何信息:

  1. 我错过了什么吗?有没有办法在IPython中使用配置文件来指定系统命令解释器?
  2. 如果!1,我是否有办法在PowerShell中启动子进程,并使用该进程本地的机器范围环境变量?
  3. 调查/测试

    通过IPython代码,我看到它正在使用os.system()将命令发送到shell,而不是subprocess.call()。这使得事情变得更复杂,因为os.system *只使用COMSPEC,在子进程*中,您可以指定要使用的可执行文件。

    我尝试加载PowerShell,设置$env:comspec变量,然后从该shell中启动IPython,但即使COMSPEC设置为set,即使在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 *中的设置来测试更多。通过在设置>中将子进程的显式可执行 Set ComSpec环境变量设置为选定值 *标志,我能够在不更改全局变量的情况下执行此操作。启动> ComSpec ,并提供powershell.exe的路径,但我不确定这是否会对使用ConEmu打开的CMD控制台产生负面影响,因为该设置是全局的(在ConEmu内)。这就是我上面问题2的原因,因为我不确定如何在PowerShell中设置进程/子局部的机器范围环境变量(如果这样的话甚至可能)。

    最后,我的梦想目标是让IPython通过配置文件支持命令shell解释器的规范,但要做到这一点,os.system()不能是使用的。我打算在我的本地副本(a'la this Python Doc)中用subprocess.call()替换它进行测试,但是如果有人已经玩过这个,或者当前有足够的优势使用我不知道的subprocess模型,我很高兴听到它。对于非Windows系统(GitHub)来说,这似乎已经完成了,但是我已经足够新了这个规模的Python,我不能肯定如果使用了这个改变就没有别的东西会破坏在条件的Windows端,以及。

    脚注

    尔加!显然,必须有10+声誉才能正确记录问题。以下是我不允许在上面发布的链接:

    • os.system - docs.python.org/3.3/library/os.html#os.system
    • subprocess - docs.python.org/3.3/library/subprocess.html
    • ConEmu - code.google.com/p/conemu-maximus5 /

3 个答案:

答案 0 :(得分:6)

您可以使用IPython的脚本魔法来执行PowerShell命令。

定义魔法

IPython profile中,修改ipython_config.py以包含以下行:

c.ScriptMagics.script_magics = ['powershell']
c.ScriptMagics.script_paths = {
        'powershell':'powershell.exe -noprofile -command -'}

-command -告诉PowerShell执行stdin文本作为命令。如果您需要加载PS配置文件,可以省略-noprofile,但速度会慢一些。

然后,您可以将%%powershell用作script cell magic

In [1]: %%powershell
   ...: 1..5
1
2
3
4
5

Custom Magics

为了使它更容易使用,我定义了自己的魔术函数来处理包含线条和单元格魔法的PowerShell命令。 (参见:defining your own magics)这可以通过将脚本放在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
----                -------------     ------ ----
d-r--         10/2/2013  10:39 AM            Program Files
d-r--         12/6/2013   1:44 PM            Program Files (x86)
d----          2/6/2014   4:33 PM            TEMP
d-r--        11/27/2013  11:10 AM            Users
d----         1/13/2014  11:21 AM            Windows

Cell magics可以将输出发送到--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'],
 ...

答案 1 :(得分:0)

这有点狡猾,但您可以使用

调用预先制作的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")

但是如果你不得不在脚本中多次调用这种类型的东西,我想它可能变得丑陋和缓慢。

答案 2 :(得分:0)

最简单的方法是在Jupiter笔记本或python shell中导入os并更新环境变量comspec

import os;
os.environ['comspec']='powershell.exe'
os.getenv('comspec')

然后使用以下命令。

!gc log.txt | select -first 10 # head
!gc -TotalCount 10 log.txt     # also head
!gc log.txt | select -last 10  # tail
!gc -Tail 10 log.txt           # also tail (since PSv3), also much faster than above option
!gc log.txt | more             # or less if you have it installed
!gc log.txt | %{ $_ -replace '\d+', '($0)' }         # sed

更多内容,请访问https://ss64.com/ps/