【问题标题】:In Python 3.x make print work like in Python 2 (as statement)在 Python 3.x 中,让 print 像在 Python 2 中一样工作(作为语句)
【发布时间】:2015-03-06 10:21:36
【问题描述】:

我想知道 print 函数是否可以像 Python 2 和更早版本一样工作(无需更改所有地方的语法)。

所以我有这样的声明:

print "Hello, World!"

而且我喜欢在 Python 3 中使用该语法。我尝试导入库 six,但没有成功(仍然是语法错误)。

【问题讨论】:

  • 大声笑,我想要完全相同的东西。我喜欢 python 3 的所有内容,除了 print 语句

标签: python function python-2.7 python-3.3


【解决方案1】:

不,你不能。 print 语句在 Python 3 中消失了;编译器不再支持它了。

可以print()像Python 2中的函数一样工作;把它放在每个使用print的模块的顶部:

from __future__ import print_function

这将在 Python 2 中删除对 print 语句的支持,就像在 Python 3 中一样,您可以使用 print() function that ships with Python 2

six 只能帮助桥接使用 Python 2 和 3 编写的代码;这包括将print 语句替换为print() 函数first

您可能想阅读Porting Python 2 Code to Python 3 howto;它还会告诉您更多此类 from __future__ 导入,并介绍诸如 ModernizeFuturize 之类的工具,这些工具可以帮助自动修复 Python 2 代码以在 Python 2 和 3 上运行。

【讨论】:

  • 很遗憾 - 我需要执行第三方提供的代码,我真的不喜欢查看所有更改所有打印的代码:/。 (你在这里描述的与我的问题相反:我确实在 python 3 中工作,但我需要运行由在 python 2 中工作的人编写的代码)
  • @paul23:对不起,错误的工具。您应该尝试使用2to3 utility 自动修复 Python 2 代码。
  • @paul23 如果您真的对 python 的语句和关键字机制感兴趣,您可能会喜欢阅读 this 文章。
  • 我的情况更糟...我有一些预处理数据,其中包含带有打印语句的对象...代码翻译器无法翻译我想的对象的成员函数。
  • @ymeng:代码翻译可以很好地处理成员函数。
【解决方案2】:

您可以使用正则表达式将 Python 2 的 print 代码替换为 Python 3:

Find:
(print) (.*)(\n)

Replace with:
$1($2)$3

【讨论】:

  • 正则表达式在什么上下文中? Perl 脚本?这将适用于所有风格的正则表达式。您能否提供一个示例(editing your answer,cmets 中没有(没有“编辑:”、“更新:”或类似内容))?
【解决方案3】:

您可以使用工具2to3Automated Python 2 to 3 code translation,正如@Martijn Pieters♦ 所说:),您可以摆脱旧python 并将更改应用于python 3,我做了一个这样的简单例子:

我创建了这个文件,python2.py:

#!python3

print 5

当我用 python 运行它时,它显然显示:

line 3
    print 5          ^
SyntaxError: Missing parentheses in call to 'print'

所以,您可以像这样通过终端对其进行转换:

这是重要的命令

$ 2to3 -w home/path_to_file/python2.py

-w 参数将写入文件,如果您只想查看未来的更改而不应用它们,只需在没有 -w 的情况下运行它。 运行后会显示类似

root: Generating grammar tables from /usr/lib/python2.7/lib2to3/PatternGrammar.txt
RefactoringTool: Refactored Desktop/stackoverflow/goto.py
--- Desktop/stackoverflow/goto.py   (original)
+++ Desktop/stackoverflow/goto.py   (refactored)
@@ -1,3 +1,3 @@
 #!python3

-print 5
+print(5)
RefactoringTool: Files that were modified:

文件将如下所示:

#!python3

print(5)

【讨论】:

    【解决方案4】:

    如果您可以覆盖 builtins.__import__ 和一个简单的正则表达式来转换没有括号的打印语句,那么您可以执行以下操作。请注意,这实际上不会更改任何文件,只是当您导入它们时,它会将代码读入字符串,调整该字符串,然后将固定代码发送到编译器/导入器

    import re
    import sys
    if sys.version_info >= (3, 0):
      import lib2to3
      from lib2to3 import main, refactor
      import os
      import types
      import builtins
      import sys
      import importlib
    
      cache = {}
    
      prevImport = builtins.__import__
    
      def customImport(path, *args, **kwargs):
        #print (path, args, kwargs)
        try:
          return fimport(path + ".py")
        except:
          return prevImport(path, *args, **kwargs)
    
      def reload(filename):
        fimport(filename.__file__, forceReload=True)
    
      def fimport(filename, forceReload=False):
        filename = os.path.abspath(filename)
        modulePath = os.path.splitext(os.path.basename(filename))[0]
        if filename in cache and not forceReload:
          execval, modifyTime, module = cache[filename]
          if modifyTime == os.path.getmtime(filename):
            return module
        f = open(filename)
        text = f.read() + "\n"
        p = re.compile("print")
        res = []
        curI = 0
        for m in p.finditer(text):
          i = m.start()
          res.append(text[curI:i])
          curI = i
          pieceTmp = text[i:].split("\n")[0]
          piece = text[i:].split("\n")[0].split("#")[0]
          pieceAfter = piece[len('print'):].strip()
          if pieceAfter[0] != '(':
            resLine = "print" + "(" + pieceAfter + ")" + "\n"
            res.append(resLine)
          else:
            res.append(pieceTmp)
          curI += len(pieceTmp)+1
        text = "".join(res)
        f.close()
        '''
        # this code can run lib2to3 if you want but just for replacing prints that is not needed
        #fixes = sorted(lib2to3.refactor.get_fixers_from_package('lib2to3.fixes'))
        fixes = ['lib2to3.fixes.fix_print']
        rt = lib2to3.main.StdoutRefactoringTool(fixes, {}, [], False, False)
        res = str(rt.refactor_string(text, name=modulePath))
        '''
        res = text
        res = compile(res, '<string>', 'exec')
        module = types.ModuleType(modulePath)
        module.__file__ = filename
        cache[filename] = (res, os.path.getmtime(filename), module)
        exec(res, module.__dict__)
        return module
    
    
      builtins.__import__ = customImport
      importlib.reload = reload
    

    如果您将此代码保存到,例如,pastimport.py,那么假设我有一个名为 juniper.py 的文件:

    def wow(a):
      print a
    

    现在如果我想从 python3 调用 juniper.py,我可以这样做

    import pastimport
    import juniper
    
    juniper.wow("bean")
    

    它会运行:)

    这可能会更快,更像是典型的带有缓存和日志记录等的导入,但我还不完全了解 pyc 文件的生成方式和时间。 c插件也可能存在边缘情况,我不确定。因此,请随意提出改进建议,但至少这是一个概念证明。我认为您应该能够实际调整解释器输入和当前文件的值,但我现在正在摆弄。

    从技术上讲,这还允许您导入任何 python2 文件(2to3 修复 xrange、print 等),如果这些文件导入其他 python2 文件,它们也会被转换,因为这会覆盖每个人都使用的导入。您还可以实现任意运算符重载、需要静态类型、实际上需要大括号,从技术上讲,甚至可以从其他语言导入代码或通过这个单一导入完全更改 python。但我离题了

    【讨论】:

    • 这将尝试在所有内容上运行 2to3,无论它是否实际上是 Python 2 代码。
    • 2to3 可以很好地与 python3 代码配合使用(它只是不做任何更改),但是是的,我同意这需要考虑很多边缘情况(例如 .pyd)。这很容易做到,因为你可以调用原始的导入函数,但我只是没有在这里添加检查。理想情况下,它也应该生成 .pyc 文件。随意提出修改建议。
    • 尝试在print(1, 2) 上运行 2to3,您会发现在 Python 3 代码上运行 2to3 并不安全。
    • 我得到(1, 2)(在具有print a 的同一个文件中)这正是python3 所做的? print(1,2)\nprint('games', end='') 之类的东西也可以正常工作
    • 嗯,没关系(我认为它确实有效,我一定是做错了什么)。所以你是对的,我相信一些案例分析可以解决这个问题,但肯定会更严重
    【解决方案5】:

    以下 sn-p 适用于交互式使用。当出现打印语法错误时,脚本再次执行失败的命令,并用 "()" for python3 括起来。

    #!/usr/bin/python3.8 -i
    import subprocess, shlex, sys, readline, traceback
    def excepthook(exctype, value, tb):
        if exctype is SyntaxError:
            index = readline.get_current_history_length()
            command = readline.get_history_item(index)
            if command.find("print") != -1:
                sp =  command.split("print")[1]
                new = "print" + "(" + sp + ")"
                eval(new)  
        else:
            traceback.print_exception(exctype, value, tb)
    sys.excepthook = excepthook
    

    【讨论】:

      猜你喜欢
      • 2016-05-29
      • 1970-01-01
      • 1970-01-01
      • 2011-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多