Настройка IPython для использования powershell вместо cmd

Искал для этого и не мог найти никого, кто уже спросил, так вот.

Я начинаю переключиться на IPython как на свою оболочку в Windows 7, и я бы хотел настроить ее так, чтобы магическая ошибка (!cmd) передавала команду в системную оболочку, используя PowerShell вместо cmd.exe, так что я могу воспользоваться усовершенствованиями, выполненными MS, но без необходимости менять мой %COMSPEC% на PowerShell (моя компания по-прежнему использует несколько байт на базе CMD для автоматизации, и я не хочу чтобы сломать их).

Я поставил свои вопросы здесь наверху, так как ответ может не требовать какой-либо информации ниже:

  • Я что-то упустил? Есть ли способ использовать конфигурационный файл в IPython для указания интерпретатора системных команд?
  • Если! 1, есть ли способ, которым я не могу запустить дочерний процесс из PowerShell с переменной окружения Machine-scope, которая является локальной для этого процесса?

Исследование/Тестирование

Просматривая код IPython, я вижу, что он использует os.system() для отправки команды в оболочку, а не subprocess.call(). Это делает вещи несколько более сложными, так как os.system * просто использует COMSPEC, где с подпроцессом * вы можете указать исполняемый файл для использования.

Я попытался загрузить PowerShell, установив переменную $env:comspec, а затем запустив 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 features.
%quickref -> Quick reference.
help      -> Python 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 features.
%quickref -> Quick reference.
help      -> Python 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 *. Я смог сделать это, не изменяя глобальную переменную, установив переменную среды Explicit executable и Set ComSpec для дочерних процессов на выбранные флаги значения * в настройках > Запуск > ComSpec и предоставив путь к powershell.exe, но я не если это будет иметь негативное влияние на консоли CMD, открытые с помощью ConEmu, так как эта настройка является глобальной (внутри ConEmu). Это привело меня к тому, чтобы задать вопрос 2 выше, так как я не уверен, как установить переменные среды Work-scope в PowerShell (если это возможно даже возможно).

В конце концов, моя цель мечты состояла бы в том, чтобы IPython поддерживал спецификацию интерпретатора командной оболочки через конфигурационный файл, но для этого os.system() не может быть использованным. Я планирую возиться с заменой его на subprocess.call() в моей локальной копии (a'la this Python Doc), чтобы проверить, но если кто-то уже играл с этим, или если есть достаточное преимущество для текущей модели с использованием 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/

Ответ 1

Вы можете использовать магию IPython script для выполнения команд PowerShell.

Определить магики

В своем профиле IPython измените ipython_config.py, чтобы включить строки:

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

-command - сообщает PowerShell о выполнении текста stdin в качестве команды. Вы можете оставить -noprofile, если вам нужно загрузить свой профиль PS, но он будет медленнее.

Затем вы можете использовать %%powershell как script cell magic.

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

Пользовательские магики

Чтобы сделать его немного проще в использовании, я определил свою собственную магическую функцию для обработки команд PowerShell как с линией, так и с ячейкой. (см. определение собственной магии). Это можно загрузить автоматически, разместив script в папке запуска профиля 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

Ячейки сотовой связи могут отправлять выходные данные в переменную с помощью --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'],
 ...

Ответ 2

Это немного изворотливый, но вы можете прибегнуть к вызову предварительно созданных сценариев powershell, используя

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

или отдельные команды:

os.system("powershell; gci | where {$_.Fullname -contains 'some stuff'}")

EDIT:

Я только что протестировал это, и, похоже, нужно открыть только один экземпляр powershell:

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

но я думаю, что это может стать уродливым и медленным, если вам придется много раз называть этот тип вещей в script.

Ответ 3

Самый простой способ - импортировать ОС и обновить переменную окружения comspec в вашем ноутбуке Jupiter или в оболочке Python.

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/