我有两个脚本,主要是在Python 3中,第二个是用Python 2编写的(它也使用Python 2库)。
我想从Python 3脚本中调用Python 2脚本中的一种方法,但我不知道如何跨越这个桥。
答案 0 :(得分:12)
您可以使用subprocess(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
答案 1 :(得分:10)
使用' execnet'可以非常优雅地完成彼此调用不同的python版本。以下功能具有魅力:
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_function
。 my_function
返回了它生成的字符串,channel.send(...)
将字符串发回。在网关的另一端channel.receive()
捕获该结果并将其返回给调用者。调用者最终在python 3模块中打印由my_function
生成的字符串。
答案 2 :(得分:6)
也许到很晚了,但是调用python2.7脚本还有一个更简单的选择:
script = ["python2.7", "script.py", "arg1"]
process = subprocess.Popen(" ".join(script),
shell=True,
env={"PYTHONPATH": "."})
答案 3 :(得分:2)
我正在使用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脚本它自己的小世界,它似乎需要它。我发布这篇文章是希望能在一段时间内拯救别人。
答案 4 :(得分:0)
注意:在liclipse IDE中运行我的python 2.x s / w时会发生这种情况。 当我从命令行上的bash脚本运行它时,它没有问题。 这是一个问题&我在混合python 2.x&时遇到的解决方案3.x脚本。
我正在运行python 2.6进程&需要调用/执行python 3.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
答案 5 :(得分:0)
如果我直接从python 3环境调用python 2可执行文件,它对我有用。
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()
答案 6 :(得分:0)
我最终在python3脚本中创建了一个新函数,该脚本包装了python2.7代码。它可以正确格式化python2.7代码创建的错误消息,并扩展了mikelsr的答案,并按照subprocess docs的建议使用run()
。
在bar.py中(python2.7代码):
def foo27(input):
return input * 2
在python3文件中:
import ast
import subprocess
def foo3(parameter):
try:
return ast.literal_eval(subprocess.run(
[
"C:/path/to/python2.7/python.exe", "-c", # run python2.7 in command mode
"from bar import foo27;"+
"print(foo27({}))".format(parameter) # print the output
],
capture_output=True,
check=True
).stdout.decode("utf-8")) # evaluate the printed output
except subprocess.CalledProcessError as e:
print(e.stdout)
raise Exception("foo27 errored with message below:\n\n{}"
.format(e.stderr.decode("utf-8")))
print(foo3(21))
# 42
当传入简单的python对象(如dicts)作为参数时,此方法有效,但不适用于由类创建的对象,例如。 numpy数组。这些必须在障碍的另一侧进行序列化和重新实例化。
答案 7 :(得分:-3)
我建议将Python2文件转换为Python3: