【问题标题】:Ignore the rest of the python file忽略python文件的其余部分
【发布时间】:2015-08-12 15:27:53
【问题描述】:

我的 python 脚本通常在文件的第一部分包含“可执行代码”(函数、类等),最后包含“测试代码”(交互式实验)。

我希望python、py_compile、pylint &c 最后完全忽略实验性的东西。

我正在为cpp 寻找类似#if 0 的东西。

如何做到这一点?

以下是一些想法及其不好的原因:

  1. sys.exit(0):适用于python,但不适用于py_compile 和pylint
  2. 将所有实验代码放在def test(): 下:我不能再将代码复制/粘贴到python REPL,因为它有重要的缩进
  3. 将所有实验代码放在带有""" 的行之间:emacs 不再正确缩进和字体化代码
  4. 一直注释和取消注释代码:我太懒了(是的,这是一个按键,但我必须记住这样做!)
  5. 将测试代码放到一个单独的文件中:我想把相关的东西放在一起

附言。我的 IDE 是 Emacs,我的 Python 解释器是 pyspark。

【问题讨论】:

  • 把测试代码放到另一个文件里?
  • 任何好的IDE/文本编辑器都应该有“切换评论”功能。它使整个评论/取消评论的事情只需点击一下。为什么你把它放在一个文件里?

标签: python python-2.7


【解决方案1】:

在您的 REPL 中使用 ipython 而不是 python 它具有更好的代码完成和自省功能,当您粘贴缩进的代码时,它可以自动“取消缩进”粘贴的代码。

因此,您可以将您的实验代码放入测试函数中,然后粘贴到各个部分,而无需担心代码缩进。

如果您要粘贴可被视为单个块的大块,则需要使用 %paste 或 %cpaste 魔法。

例如。

    for i in range(3):
        i *= 2 
        # with the following the blank line this is a complete block

        print(i)

普通粘贴:

In [1]:         for i in range(3):
   ...:                 i *= 2
   ...:     

In [2]:             print(i)
4

使用%paste

In [3]: %paste
        for i in range(10):
            i *= 2

            print(i)

## -- End pasted text --
0
2
4

In [4]: 

PySpark 和 IPython

也可以在增强的 Python 解释器 IPython 中启动 PySpark。 PySpark 适用于 IPython 1.0.0 及更高版本。要使用 IPython,请在运行 bin/pyspark 时将 IPYTHON 变量设置为 1:1

$ IPYTHON=1 ./bin/pyspark

【讨论】:

  • 大概这个答案的主旨是ipython 减少了选项2的缺点。
  • 是的,感谢您澄清这一点。我并不总是最擅长解释我的思维过程背后的原因。
【解决方案2】:

不幸的是,没有广泛(或任何)标准来描述您所谈论的内容,因此很难让一堆特定于 python 的东西像这样工作。

但是,您可以将这些命令包装成只读取到一个能指的方式。例如(假设您使用的是 unix 系统):

cat $file | sed '/exit(0)/q' |sed '/exit(0)/d' 

该命令将一直读取,直到找到“exit(0)”。您可以将其通过管道传输到您的检查器中,或者创建一个您的检查器读取的临时文件。您可以在您的路径上创建包装器可执行文件,可能与您的编辑器一起使用。

Windows 或许可以使用类似的技术。

我可能会建议一种不同的方法。单独的文件可能是最好的。您可能会探索 iPython 笔记本作为一种可能的解决方案,但我不确定您的用例到底是什么。

【讨论】:

    【解决方案3】:

    遵循类似于选项 2 的内容。
    我通常把实验代码放在main方法中。

    def main ():
        *experimental code goes here *
    

    如果你想执行实验代码,只需调用 main。

    main()
    

    【讨论】:

      【解决方案4】:

      使用 python-mode.el 将任意块标记为部分 - 例如通过py-sectionize-region。

      比打电话py-execute-section。

      评论后更新:

      python-mode.el 由 melpa 提供。

      M-x list-packages RET

      寻找python-mode - 内置的python.el提供'python,而python-mode.el提供'python-mode。

      开发刚刚搬到这里:https://gitlab.com/python-mode-devs/python-mode

      【讨论】:

      • emacs自带的标准python模式没有section。你在说python-x吗?
      【解决方案5】:

      我认为处理这个问题的标准('Pythonic')方法是这样做:

      class MyClass(object):
          ...
      
      def my_function():
          ...
      
      if __name__ == '__main__':
          # testing code here
      

      发表评论后编辑

      我认为使用普通的 Python 解释器不可能实现您想要的。你可以看看 IEP Python 编辑器(website,bitbucket):它支持类似于 Matlab 的单元格模式,其中单元格可以用双注释字符定义(##):

      ## main code
      
      class MyClass(object):
          ...
      
      def my_function():
          ...
      
      ## testing code
      
      do_some_testing_please()
      

      从##-beginning 行到下一个这样的行或文件结尾的所有代码构成一个单元格。 每当光标位于特定单元格中并且您按下某个热键(默认为 Ctrl+Enter)时,该单元格中的代码就会在当前运行的解释器中执行。 IEP 的另一个特点是可以用 F9 执行选定的代码;一个非常标准的功能,但这里的好处是 IEP 将巧妙地处理空白,因此只需从方法内部选择和粘贴内容就会自动工作。

      【讨论】:

      • @sds 查看我的编辑,我认为您需要特定的编辑器/IDE 功能来完成您所追求的工作。
      • 我的ide是emacs;我的 repl 是 pyspark
      • 很想知道为什么这被否决了;我提到的原始选项并不完全是 OP 的选项 2(它略有不同,因为测试代码不在方法内,而是在模块末尾的“标准”if ...: 块中)。我在编辑中提到的第二个选项确实是对解决方案的真正尝试;就像我说的那样,我认为使用标准的、非工具增强的 Python 是不可能实现这一点的。
      • 您好,这里是downvoter。我对这个问题的每一个答案都投了反对票,在我看来,这些答案似乎因充分阅读该问题而无效。例如,您的第一个解决方案未能解决 reason OP 未使用选项 2,即它不使用基本缩进。您的第二个解决方案无法解释这样一个事实,即这会破坏 IDE 中的语法突出显示。
      • __name__ == '__main__' 检查通常不特别用于测试,但通常用于区分文件是作为模块导入还是作为脚本运行(即允许两者)。
      【解决方案6】:

      我建议您使用适当的版本控制系统,将“真实”和“实验”部分分开。

      例如,使用 Git,您只能在提交中包含不带实验部分的真实代码(使用 add -p),然后暂时 stash 包含实验部分以运行各种工具。

      您还可以将实验部分保存在他们自己的分支中,然后在需要时将其 rebase 放在非实验部分之上。

      【讨论】:

      • 那就好好利用吧!
      • 我的问题与版本控制正交。我不想为我在文件中插入的每个逗号进行提交。
      • 那我没有更好的主意了,抱歉。
      • 顺便说一句,我的建议与您提交的粒度无关。唯一的要求是您将实验部分和非实验部分分开。
      【解决方案7】:

      另一种可能性是将测试作为doctests 放入代码的文档字符串中,这无疑只适用于更简单的情况。

      这样,doctest 模块仅将它们视为可执行代码,否则视为 cmets。

      【讨论】:

        猜你喜欢
        • 2010-10-31
        • 1970-01-01
        • 2020-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多