Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用PythonV3.x和C API解释PythonV2.5代码(关于整数除法)_Python_Python 3.x_Integer Division_Python 2.5_C Api - Fatal编程技术网

使用PythonV3.x和C API解释PythonV2.5代码(关于整数除法)

使用PythonV3.x和C API解释PythonV2.5代码(关于整数除法),python,python-3.x,integer-division,python-2.5,c-api,Python,Python 3.x,Integer Division,Python 2.5,C Api,我有一个无法控制的2.5版Python代码,因为它是从支持Python 2.5的第三方软件导出的 我的机器上有Python v3.3,我希望以某种方式模拟v2.5 使用C API。我主要关心的是整数除法,它不同于v2.x和v3.x 例如,我有以下代码: a=1 b=a/2 c=a/2. 我希望(使用v3.x)以某种方式将其解释为: 我能做点什么吗?是否有任何方法可以将代码解释为Python v2.5?我认为2to3脚本不适用于我的案例,也不适用于六模块 我还发现了与我相关的这个问题: 谢谢这

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

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

例如,我有以下代码:

a=1
b=a/2
c=a/2.
我希望(使用v3.x)以某种方式将其解释为:

我能做点什么吗?是否有任何方法可以将代码解释为Python v2.5?我认为2to3脚本不适用于我的案例,也不适用于六模块

我还发现了与我相关的这个问题:


谢谢

这听起来是个糟糕的主意,您将遇到更严重的问题,将Python 2.5代码解释为Python 3,就像每个
一样,除了
语句是语法错误,字符串是错误的类型(或者,如果您解决了这个问题,
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级别以下的内部类型对象,例如,访问它们的
tp\u as\u number
结构,并将它们的
nb\u floordiv
函数复制到它们的
nb\u truediv
插槽中。即使这样,也可能不会改变一切


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

编写一个导入钩子可能是一个太大的主题,不可能在几个段落中作为一个答案的序言来涵盖,所以请参见这一部分

现在,至于导入钩子的实际作用,您要做的是替换
MyLoader.exec\u模块
方法。与此相反:

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))
那么,我们如何“以某种方式操纵树”?通过建立一个

每个
/
表达式都是一个
BinOp
节点,其中
op
是不带属性的
Div
节点,
是要分割的值。如果我们想用
/
将其更改为相同的表达式,这是相同的
BinOp
,但是
op
FloorDiv

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

class DivTransformer(ast.NodeTransformer):
    def visit_Div(self, node):
        return ast.copy_location(ast.FloorDiv(), node)
我们的“以某种方式操纵树”变成:


如果您想根据除数是否为整型文字在
floordiv
truediv
之间进行选择,正如您的示例所暗示的,这并不难:

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
    如果最终控制
    \uuu*div\uuu
    /
    \uuu*rdiv\uuu>的参数(通过精确复制解释器为此使用的规则)是整数值
  • …还有别的吗

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

您的意思是
a//2
不起作用?Python3-x将其定义为“整数除法”。@usr2564301不,他说他希望他的Python3解释器在Python2上下文中解析
b=a/2
,也就是说:
b=a//2
将第三方库移植到Python3。Python2.5和Python3.3在几年前就已经达到了支持生命的尽头。或者只是在Python2.5中作为子进程运行Python2.5代码。“我的机器上有Python3.3”也可以获得2.5。“软件包管理器”在这方面非常出色,因此您可以为不同的版本创建不同的环境。他们希望将
a/2.
视为truediv,而不是将所有分区转换为floordiv。@user2357112我添加了一个部分来实现这一效果。如前所述,这不是一个定义明确的要求。而弄清楚如何定义它实际上是困难的一部分。例如,即使
a
是浮点数,他们是否真的希望
a/2
成为truediv?@abarnert谢谢你的回答。由于我是Python新手,因此我将进一步研究它。然而,为了回答您的问题,我希望在理想情况下这样做:python3.像python2x一样解释(代码为v2x)。我希望得到与使用python v2.x解释器时相同的结果。@tsahmatsis是
code\u v2x
源代码吗?函数对象?模块名称…?而且,正如我在问题中提到的:是否有一个原因不能仅仅是
子流程.run(['python2.5','code_v2x.py',…一些参数…],…)
?因为到目前为止,这是最容易做到的。@abarnert code_v2x是源代码,应该用与Python v2.x使用v3.x相同的方式来解释。
tree = DivTransformer().visit(tree)
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