从Python3调用Python2脚本

从Python3调用Python2脚本,python,Python,我有两个脚本,主要是用Python3编写的,第二个是用Python2编写的(它还使用Python2库) 在Python2脚本中有一个方法我想从Python3脚本中调用,但我不知道如何跨越这座桥 您可以使用子流程(python模块)从bash运行python2,并执行以下操作: 从python 3: #!/usr/bin/env python3 import subprocess python3_command = "py2file.py arg1 arg2" # launch your py

我有两个脚本,主要是用Python3编写的,第二个是用Python2编写的(它还使用Python2库)


在Python2脚本中有一个方法我想从Python3脚本中调用,但我不知道如何跨越这座桥

您可以使用子流程(python模块)从bash运行python2,并执行以下操作:

python 3

#!/usr/bin/env python3
import subprocess

python3_command = "py2file.py arg1 arg2"  # launch your python2 script using bash

process = subprocess.Popen(python3_command.split(), stdout=subprocess.PIPE)
output, error = process.communicate()  # receive output from the python2 script

在输出存储python 2返回的任何内容的地方,可以非常优雅地使用。以下功能不执行魅力:

import execnet

def call_python_version(Version, Module, Function, ArgumentList):
    gw      = execnet.makegateway("popen//python=python%s" % Version)
    channel = gw.remote_exec("""
        from %s import %s as the_function
        channel.send(the_function(*channel.receive()))
    """ % (Module, Function))
    channel.send(ArgumentList)
    return channel.receive()
示例:用Python 2.7编写的
my_module.py

def my_function(X, Y): 
    return "Hello %s %s!" % (X, Y)
然后执行以下函数调用

result = call_python_version("2.7", "my_module", "my_function",  
                             ["Mr", "Bear"]) 
print(result) 
result = call_python_version("2.7", "my_module", "my_function",  
                             ["Mrs", "Wolf"]) 
print(result)
导致

Hello Mr Bear!
Hello Mrs Wolf!
发生的情况是“网关”被实例化
对于带有
channel.receive()
的参数列表。一旦输入,它就被翻译并传递到
my\u函数
my_函数
返回它生成的字符串,并
channel.send(…)
将字符串发回。在网关的另一端,channel.receive()捕获该结果并将其返回给调用者。调用者最终打印python 3模块中由
my_函数产生的字符串。

我正在用python 3运行python代码,但我需要一个用python 2.7编写的工具(ocropus)。我花了很长时间在子流程中尝试所有这些选项,但一直出现错误,脚本无法完成。从命令行,它运行得很好。所以我最终尝试了一些简单的方法,但我在网上搜索中没有找到。我将ocropus命令放在bash脚本中:

#!/bin/bash

/usr/local/bin/ocropus-gpageseg $1
我使用子流程调用bash脚本

command = [ocropus_gpageseg_path,  current_path]
process = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
output, error = process.communicate()
print('output',output,'error',error)

这确实给了ocropus脚本它自己的小世界,这似乎是它所需要的。我发布这篇文章是希望它能为其他人节省一些时间。

注意:这是在liclipse IDE中运行python 2.x s/w时发生的。 当我在命令行上从bash脚本运行它时,它没有问题。 这里是我在混合Python2.x和3.x脚本时遇到的一个问题和解决方案

我正在运行一个Python2.6进程&需要调用/执行Python3.6脚本。 环境变量PYTHONPATH被设置为指向2.6 python s/w,因此出现以下问题:

File "/usr/lib64/python2.6/encodings/__init__.py", line 123
raise CodecRegistryError,\
这导致3.6 python脚本失败。 因此,我没有直接调用3.6程序,而是创建了一个bash脚本,该脚本将PYTHONPATH环境变量核化

#!/bin/bash
export PYTHONPATH=
## Now call the 3.6 python scrtipt
./36psrc/rpiapi/RPiAPI.py $1

如果我直接从Python3环境调用Python2可执行文件,这对我来说是可行的

python2_command = 'C:\Python27\python.exe python2_script.py arg1'
process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE)
output, error = process.communicate()

python3_command = 'python python3_script.py arg1'
process = subprocess.Popen(python3_command.split(), stdout=subprocess.PIPE)
output, error = process.communicate()

可能会延迟,但对于call python2.7脚本,还有一个更简单的选项:

script = ["python2.7", "script.py", "arg1"]    
process = subprocess.Popen(" ".join(script),
                                        shell=True,  
                                        env={"PYTHONPATH": "."})

我建议将Python2文件转换为Python3:


我最终在python3脚本中创建了一个新函数,它封装了python2.7代码。它正确格式化python2.7代码创建的错误消息,并根据建议扩展mikelsr的答案和使用
run()

在bar.py中(python2.7代码):

def foo27(输入):
返回输入*2
在python3文件中:

导入ast
导入子流程
def foo3(参数):
尝试:
返回ast.literal_eval(subprocess.run(
[
“C:/path/to/python2.7/python.exe”、“-C”#以命令模式运行python2.7
"来自酒吧(27);+
“print(foo27({}))”。format(parameter)#打印输出
],
捕获输出=真,
检查=正确
).stdout.decode(“utf-8”)#评估打印输出
除subprocess.CalledProcessError为e外:
印刷品(e.stdout)
引发异常(“foo27出错,消息如下:\n\n{}”
.格式(e.stderr.decode(“utf-8”))

当传递简单的python对象(如dicts)作为参数时,这是有效的,但对于类创建的对象(如numpy数组)不起作用。必须在屏障的另一端对这些方法进行序列化和重新实例化。

该特定方法是否依赖于Python 2特定的功能?是否可以将其转换为Python 3?如果3x不支持它,则无法运行它。另一种方法可能是通过系统调用调用Python 2脚本,并将结果存储在文件中。。。但是只有当所有其他方法都失败的时候。@GaryYe一个主意如果你需要的输出可以转换成文本文件或类似的东西,你可以创建一个python2脚本来输出你需要的东西(到一个文件或控制台)。然后,您可以通过python3中的子进程运行脚本(假设您同时安装了Python 2.x和Python 3.x),并通过子进程或打开由Python 2脚本创建的文件来获得结果。是的,只需将其桥接,就像桥接两种完全不同的语言一样。。。。你只需要想出一种接口,它可以处理你试图传递的任何数据。你可以发送和接收文本以外的对象吗?是的,你可以!这就是“execnet”的优点。它以兼容的方式序列化对象。@Frank ReneSchäfer我试着运行你的函数来调用一个python2函数,该函数返回浮点和字符串的元组。出现错误,提示
DumpError:无法序列化
。你知道我该如何解决这个问题吗?有人能评论一下这个方法相对于纯Python 2的性能吗?我认为需要启动另一个Python解释器以及序列化和反序列化一定会带来一些损失。“
execnet
目前处于仅维护模式,主要是因为它仍然是
pytest xdist
插件的后端。不要在新项目中使用。”嗯,现在呢?如果你想在执行下一个Python线之前等待子进程完成,考虑使用<代码>子进程。调用< /代码>我不明白这是怎么回答的。这使用python3解释器。对我来说,它抛出
OSError:[Errno 2]没有这样的文件或目录
(我正在尝试启动Py 3 fr)
print(foo3(21))
# 42