Настройка 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/