IPython 检测自动魔法
IPython detect automagics
如果我写
ls *.txt
进入 IPython 笔记本中的单元格,然后它会正确执行。但是,如果我尝试使用 TransformerManager().transform_cell
转换单元格,什么也没有发生,我得到无效的 Python 语法:
>>> from IPython.core.inputtransformer2 import TransformerManager
>>> import ast
>>> TransformerManager().transform_cell('ls *.txt')
'ls *.txt\n'
>>> ast.parse('ls *.txt\n')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/ignoring_gravity/miniconda3/envs/tmp/lib/python3.8/ast.py", line 47, in parse
return compile(source, filename, mode, flags,
File "<unknown>", line 1
ls *.txt
^
SyntaxError: invalid syntax
有没有办法以 returns 有效 Python 代码的方式转换自动魔法?没有 automagic 的等效代码将转换如下:
>>> TransformerManager().transform_cell('!ls *.txt')
"get_ipython().system('ls *.txt')\n"
我正在寻找的是一种检测自动魔法的方法无需运行代码
Automagics 是 运行 内核的一个特性,而不是语法。例如,cd
本身是一个有效的自动魔法,除非它被 Python 名称遮蔽,或者就此而言,如果 %automagic
被禁用。
In [1]: cd
/home/wja
In [2]: cd = 'CD'
In [3]: cd
Out[3]: 'CD'
In [4]: del cd
In [5]: cd
/home/wja
In [6]: %automagic 0
Automagic is OFF, % prefix IS needed for line magics.
In [7]: cd
Traceback (most recent call last):
File "<ipython-input-7-9c6465b4471e>", line 1, in <module>
cd
NameError: name 'cd' is not defined
在幕后,据我所知,当一个单元格抛出某些错误,如 SyntaxError
或 NameError
,它被发送到预过滤器,如果它可以转化为魔法,它是被预过滤器捕获 AutoMagicChecker
and transformed. My understanding is mostly based on this comment on an IPython GitHub issue:
Input transformers are applied line-by-line, but prefilters are only applied when the code is run. So 'invalid' [an invalid line] triggers an attempt to execute, and then prefilters step in and may transform it into valid code.
-- Thomas Kluyver,2015 年 7 月 11 日
现在,如果您有 运行 内核,您可以使用预过滤器,如下所示:
In [1]: ip = get_ipython() # The running kernel
In [3]: source = ip.prefilter('cd') # Transform
In [4]: source
Out[4]: "get_ipython().run_line_magic('cd', '')"
In [5]: exec(source) # Run, just to prove it works
/home/wja
或者,长途跋涉:
In [2]: from IPython.core.splitinput import LineInfo
In [3]: line_info = LineInfo('cd') # Parse
In [4]: ip = get_ipython()
In [5]: ip.prefilter_manager.checkers # List of prefilters
Out[5]:
[<EmacsChecker(priority=100, enabled=False)>,
<MacroChecker(priority=250, enabled=True)>,
<IPyAutocallChecker(priority=300, enabled=True)>,
<AssignmentChecker(priority=600, enabled=True)>,
<AutoMagicChecker(priority=700, enabled=True)>,
<PythonOpsChecker(priority=900, enabled=True)>,
<AutocallChecker(priority=1000, enabled=True)>]
In [6]: for checker in ip.prefilter_manager.checkers:
...: handler = checker.check(line_info)
...: if handler: # Find the first one that matches
...: break
...:
In [7]: handler
Out[7]: <IPython.core.prefilter.MagicHandler at 0x7f01e8ccc7f0>
In [10]: handler.handle(line_info) # Transform
Out[10]: "get_ipython().run_line_magic('cd', '')"
如果我写
ls *.txt
进入 IPython 笔记本中的单元格,然后它会正确执行。但是,如果我尝试使用 TransformerManager().transform_cell
转换单元格,什么也没有发生,我得到无效的 Python 语法:
>>> from IPython.core.inputtransformer2 import TransformerManager
>>> import ast
>>> TransformerManager().transform_cell('ls *.txt')
'ls *.txt\n'
>>> ast.parse('ls *.txt\n')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/ignoring_gravity/miniconda3/envs/tmp/lib/python3.8/ast.py", line 47, in parse
return compile(source, filename, mode, flags,
File "<unknown>", line 1
ls *.txt
^
SyntaxError: invalid syntax
有没有办法以 returns 有效 Python 代码的方式转换自动魔法?没有 automagic 的等效代码将转换如下:
>>> TransformerManager().transform_cell('!ls *.txt')
"get_ipython().system('ls *.txt')\n"
我正在寻找的是一种检测自动魔法的方法无需运行代码
Automagics 是 运行 内核的一个特性,而不是语法。例如,cd
本身是一个有效的自动魔法,除非它被 Python 名称遮蔽,或者就此而言,如果 %automagic
被禁用。
In [1]: cd
/home/wja
In [2]: cd = 'CD'
In [3]: cd
Out[3]: 'CD'
In [4]: del cd
In [5]: cd
/home/wja
In [6]: %automagic 0
Automagic is OFF, % prefix IS needed for line magics.
In [7]: cd
Traceback (most recent call last):
File "<ipython-input-7-9c6465b4471e>", line 1, in <module>
cd
NameError: name 'cd' is not defined
在幕后,据我所知,当一个单元格抛出某些错误,如 SyntaxError
或 NameError
,它被发送到预过滤器,如果它可以转化为魔法,它是被预过滤器捕获 AutoMagicChecker
and transformed. My understanding is mostly based on this comment on an IPython GitHub issue:
Input transformers are applied line-by-line, but prefilters are only applied when the code is run. So 'invalid' [an invalid line] triggers an attempt to execute, and then prefilters step in and may transform it into valid code.
-- Thomas Kluyver,2015 年 7 月 11 日
现在,如果您有 运行 内核,您可以使用预过滤器,如下所示:
In [1]: ip = get_ipython() # The running kernel
In [3]: source = ip.prefilter('cd') # Transform
In [4]: source
Out[4]: "get_ipython().run_line_magic('cd', '')"
In [5]: exec(source) # Run, just to prove it works
/home/wja
或者,长途跋涉:
In [2]: from IPython.core.splitinput import LineInfo
In [3]: line_info = LineInfo('cd') # Parse
In [4]: ip = get_ipython()
In [5]: ip.prefilter_manager.checkers # List of prefilters
Out[5]:
[<EmacsChecker(priority=100, enabled=False)>,
<MacroChecker(priority=250, enabled=True)>,
<IPyAutocallChecker(priority=300, enabled=True)>,
<AssignmentChecker(priority=600, enabled=True)>,
<AutoMagicChecker(priority=700, enabled=True)>,
<PythonOpsChecker(priority=900, enabled=True)>,
<AutocallChecker(priority=1000, enabled=True)>]
In [6]: for checker in ip.prefilter_manager.checkers:
...: handler = checker.check(line_info)
...: if handler: # Find the first one that matches
...: break
...:
In [7]: handler
Out[7]: <IPython.core.prefilter.MagicHandler at 0x7f01e8ccc7f0>
In [10]: handler.handle(line_info) # Transform
Out[10]: "get_ipython().run_line_magic('cd', '')"