gpt4 book ai didi

python - 使用 Python v3.x 和 C API 解释 Python v2.5 代码(关于整数除法)

转载 作者:行者123 更新时间:2023-11-30 22:11:43 24 4
gpt4 key购买 nike

我有一个我无法控制的 v2.5 Python 代码,因为它是从支持 Python v2.5 的第三方软件导出的。

我的机器上有 Python v3.3,我想以某种方式模拟 v2.5使用 C API。我主要关心的是 v2.x 和 v3.x 之间的整数除法不同。

例如我有以下代码:

a=1
b=a/2
c=a/2.

我希望以某种方式将其解释为(使用 v3.x):

a=1
b=a//2
c=a/2.

我可以做点什么吗?有没有办法像我有Python v2.5一样解释代码?我认为 2to3 脚本不适用于我的情况,六个模块也不适用于。

我还发现了这个与我相关的问题: Python 2 and Python 3 dual development

谢谢

最佳答案

这听起来是一个坏主意,而且将 Python 2.5 代码解释为 Python 3 时会遇到更严重的问题,就像每个 except 语句都是语法错误,字符串是错误的类型(或者,如果你修复了这个问题,s[i] 返回一个 int 而不是一个字节),等等。

<小时/>

这里要做的显而易见的事情是将代码移植到仍然受支持的 Python 中。

如果由于某种原因这确实不可能,那么最简单的方法可能是围绕您需要运行的代码编写一个简单的 Python 2.5 包装器,该包装器通过 sys.argv 获取输入并/或sys.stdin并通过sys.exit和/或sys.stdout返回结果。

然后,你就这样调用它:

p = subprocess.run(['python2.5', 'mywrapper.py', *args], capture_output=True)
if p.retcode:
raise Exception(p.stderr.decode('ascii'))
results = p.stdout.splitlines().decode('ascii')
<小时/>

但是,如果您真的想这样做,并且这确实是您唯一的问题......这仍然不是这样做的方法

您必须进入 C API 级别以下,进入内部类型对象,例如 struct PyFloat_Type ,访问其 tp_as_number 结构,并将其 nb_floordiv 函数复制到其 nb_truediv 槽中。即使这样也可能无法改变一切。

<小时/>

更好的解决方案是构建一个导入钩子(Hook),在编译 AST 之前对其进行转换。

编写导入钩子(Hook)可能是一个太大的主题,无法用几段文字作为答案的前言来涵盖,所以请参阅 this question对于那部分。

现在,至于导入钩子(Hook)实际上做了什么,您要做的就是替换 MyLoader.exec_module 方法。而不是这个:

def exec_module(self, module):
with open(self.filename) as f:
data = f.read()

# manipulate data some way...

exec(data, vars(module))

您将执行以下操作:

def exec_module(self, module):
with open(self.filename) as f:
data = f.read()

tree = ast.parse(data)

# manipulate tree in some way

code = compile(tree, self.filename, 'exec')
exec(code, vars(module))

那么,我们如何“以某种方式操纵树”?通过构建 NodeTransformer .

每个/表达式都是一个BinOp节点,其中op是没有属性的Div节点,并且leftright 是要除的值。如果我们想将其更改为相同的表达式,但使用 //,那就是相同的 BinOp,但其中 opFloorDiv .

因此,我们只需访问 Div 节点并将其转换为 FloorDiv 节点即可:

class DivTransformer(ast.NodeTransformer):
def visit_Div(self, node):
return ast.copy_location(ast.FloorDiv(), node)

我们的“#以某种方式操纵树”变成:

tree = DivTransformer().visit(tree)
<小时/>

如果您想根据除数是否是整数文字在 floordivtruediv 之间进行选择,正如您的示例似乎暗示的那样,这并不难:

class DivTransformer(ast.NodeTransformer):
def visit_BinOp(self, node):
if isinstance(node.op, ast.Div):
if isinstance(node.right, ast.Num) and isinstance(node.right.val, int):
return ast.copy_location(ast.BinOp(
left=node.left,
op=ast.copy_location(ast.FloorDiv(), node.op),
right=node.right))
return node
<小时/>

但我怀疑这就是你真正想要的。事实上,你真正想要的可能很难定义。您可能想要类似的东西:

  • floordiv 如果两个参数在运行时都是整数值
  • floordiv 如果参数最终将控制 __*div__/__*rdiv__ (通过精确再现所使用的规则解释器认为)是一个整数值。
  • ……还有什么吗?

无论如何,执行此操作的唯一方法是将 BinOp 替换为您编写的 mydiv 函数的 Call,例如,坚持使用builtins。然后,该函数执行类型切换以及实现规则所需的任何其他操作,然后返回 a/b返回 a//b

关于python - 使用 Python v3.x 和 C API 解释 Python v2.5 代码(关于整数除法),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51332086/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com