Windows 将IPython配置为使用powershell而不是cmd

Windows 将IPython配置为使用powershell而不是cmd,windows,powershell,ipython,Windows,Powershell,Ipython,搜索了这个,但似乎找不到任何已经问过的人,所以这里开始 我开始在Windows 7上切换到IPython作为我的go to shell,我想对它进行配置,以便bang magic(!cmd)将命令传递给系统shell时使用PowerShell而不是cmd.exe,这样我就可以利用MS所做的增强,但不必将我的%COMSPEC%更改为PowerShell(我的公司仍然使用几种基于CMD的.bat实现自动化,我不想破坏它们) 我将在顶部发布我的问题,因为答案可能不需要以下任何信息: 我错过什么了吗?有

搜索了这个,但似乎找不到任何已经问过的人,所以这里开始

我开始在Windows 7上切换到IPython作为我的go to shell,我想对它进行配置,以便bang magic(
!cmd
)将命令传递给系统shell时使用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显示为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)

    更改Machine-scope环境变量似乎可以满足我的要求,但由于前面提到的原因,这对我来说不是一个有效的解决方案

    [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*中的设置测试了更多的解决方案。通过在“设置”>“启动”>“ComSpec”中将子进程的显式可执行文件和ComSpec环境变量设置为selected value*flags,并提供powershell.exe的路径,我可以在不更改全局变量的情况下完成此操作,但我不确定这是否会对使用ConEmu打开的CMD控制台产生负面影响,因为该设置是全局的(在ConEmu内)。这就是导致我提出上述问题2的原因,因为我不确定如何在PowerShell中设置进程/子本地、机器范围的环境变量(如果可能的话)

    最后,我的理想目标是让IPython通过配置文件支持命令shell解释器的规范,但要做到这一点,
    os.system()
    不能作为使用的工具。我打算在本地副本(a'la this)中修改一下,用
    subprocess.call()替换它进行测试,但是如果有人已经使用过它,或者如果当前模型比使用
    subprocess
    有足够的优势,而我不知道,我会很高兴听到这个消息。看起来这项工作已经在非Windows系统()上进行了,但我对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/

    这有点狡猾,但您可以使用调用预先制作的powershell脚本

    os.system('powershell C:\file.ps1')

    或者像这样的单个命令:

    os.system(“powershell;gci |其中{$\.Fullname-包含一些东西”)

    编辑:

    我刚刚测试了这个,它似乎只需要打开一个powershell实例:

    os.system(“powershell;gci;gc C:\windows\system32\drivers\etc\services;[system.net.dns]::gethostbyaddress('203.20.74.6')|更多”)


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

    您可以使用IPython的脚本magics执行PowerShell命令

    定义魔法 在中,修改
    ipython_config.py
    以包括以下行:

    c.ScriptMagics.script_magics = ['powershell']
    c.ScriptMagics.script_paths = {
            'powershell':'powershell.exe -noprofile -command -'}
    
    -command-
    告诉PowerShell将stdin文本作为命令执行。如果需要加载PS配置文件,可以省去
    -noprofile
    ,但速度会慢一些

    然后,您可以使用
    %%powershell
    作为一个应用程序

    自定义魔法 为了使它更易于使用,我定义了自己的magic函数,用line和cell magics处理PowerShell命令。(请参阅:)将脚本放置在IPython配置文件的启动文件夹中,可以自动加载该脚本。(即
    ~\.ipython\profile\u default\startup\05-powershell\u magic.py

    用法示例 要使用
    %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
    将输出发送到变量:


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

    导入操作系统
    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
    
    还有莫
    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
    
    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'],
     ...
    
    !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