【问题标题】:Roundtrip IPython transform_cell往返 IPython transform_cell
【发布时间】:2021-06-02 09:31:47
【问题描述】:

考虑以下示例:

>>> from IPython.core.inputtransformer2 import TransformerManager
>>> src = """\
... foo = !ls
... !!ls
... """
>>> TransformerManager().transform_cell(src)
"foo = get_ipython().getoutput('ls')\nget_ipython().getoutput('ls')\n"

!ls!!ls 都转换为 get_ipython().getoutput('ls')

如果我只看到TransformerManager().transform_cell的输出,有没有办法找回原始来源?

有没有办法判断get_ipython().get_output(<some string>)是来自!<some string>还是!!<some string>

【问题讨论】:

  • !!ls 应该怎么做?
  • 不确定我是否理解您的问题
  • 它有什么作用?就像!ls 打印出目录中的当前文件,但是你代码中的!!ls 呢?
  • 这是有效的 IPython 语法——我并不关心它的作用,而是关心往返有效的 IPython 语法

标签: python ipython


【解决方案1】:

让我们仔细看看 TransformerManager 如何在后台工作以识别 ipython 特殊命令:

TransformerManager 尝试将每一行与以下结构之一匹配:

  • 魔术分配 (%%my ipython magic)
  • 系统分配 (foo = !cmd)
  • 转义命令(!cmd!!cmd

系统分配

system assigns 的情况下,= 符号后面的第一个! 被剥离,后面的任何内容都用作get_ipython().getoutput 的参数。

例如: foo = !ls -> foo = get_ipython().getoutput('ls')

转义命令

在所谓的“escaped commands”的情况下,即没有赋值的系统调用,!cmd 之间存在差异,它被转换为get_ipython().system(cmd)!!cmd,它变成get_ipython().getoutput(cmd) .

因此,我们可以通过使用一些基本的正则表达式来确定使用的感叹号的数量来检测分配是否存在:

import re

def get_number_exclamation_marks(transformed_line):
    """
    Takes the output of TransformerManager for one ipython line, and returns the
    number of exclamation marks used in the system call. If no system call
    is present, returns 0.
    """
    if re.search(r"= *get_ipython\(\)\.getoutput\(", transformed_line)\
    or re.search(r"get_ipython\(\)\.system\(", transformed_line):
        return 1
    if re.search(r"get_ipython\(\)\.getoutput\(", transformed_line):
        return 2
    return 0

注意:foo=!!cmd 的情况不被上述函数处理,因为它是无效的 ipython 语法。

【讨论】:

  • 谢谢 - 我会使用 ast-parsing 来检测分配而不是正则表达式,但这个想法似乎是正确的。谢谢!你确定这些是唯一需要考虑的情况吗?
  • 很确定,是的:) 如果您想仔细检查,我在初始答案中链接了 ipython 源代码的相关部分,但这很简单,我不太担心错过任何边缘情况。
猜你喜欢
  • 2016-10-27
  • 2014-03-08
  • 2021-05-27
  • 2015-04-02
  • 1970-01-01
  • 2019-04-11
  • 2013-12-28
  • 2018-03-08
  • 2011-02-26
相关资源
最近更新 更多