假设我有两个文件:
# spam.py
import library_Python3_only as l3
def spam(x,y)
return l3.bar(x).baz(y)
和
# beans.py
import library_Python2_only as l2
...
现在假设我希望从 beans
中调用 spam
。这不是直接可能的,因为这两个文件都依赖于不兼容的 Python 版本。当然,我可以 Popen
一个不同的 python 进程,但是我怎样才能传入参数并检索结果而没有太多的流解析痛苦呢?
最佳答案
这是我实际测试过的使用 subprocess
和 pickle
的完整示例实现。请注意,您需要在 Python 3 端显式使用协议(protocol)版本 2 进行酸洗(至少对于 Python 3.5.2 和 Python 2.7.3 的组合)。
# py3bridge.py
import sys
import pickle
import importlib
import io
import traceback
import subprocess
class Py3Wrapper(object):
def __init__(self, mod_name, func_name):
self.mod_name = mod_name
self.func_name = func_name
def __call__(self, *args, **kwargs):
p = subprocess.Popen(['python3', '-m', 'py3bridge',
self.mod_name, self.func_name],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
stdout, _ = p.communicate(pickle.dumps((args, kwargs)))
data = pickle.loads(stdout)
if data['success']:
return data['result']
else:
raise Exception(data['stacktrace'])
def main():
try:
target_module = sys.argv[1]
target_function = sys.argv[2]
args, kwargs = pickle.load(sys.stdin.buffer)
mod = importlib.import_module(target_module)
func = getattr(mod, target_function)
result = func(*args, **kwargs)
data = dict(success=True, result=result)
except Exception:
st = io.StringIO()
traceback.print_exc(file=st)
data = dict(success=False, stacktrace=st.getvalue())
pickle.dump(data, sys.stdout.buffer, 2)
if __name__ == '__main__':
main()
Python 3 模块(使用 pathlib
模块进行展示)
# spam.py
import pathlib
def listdir(p):
return [str(c) for c in pathlib.Path(p).iterdir()]
使用 spam.listdir
# beans.py
import py3bridge
delegate = py3bridge.Py3Wrapper('spam', 'listdir')
py3result = delegate('.')
print py3result
关于python - 使用不同的 Python 版本调用 Python 函数最接近的方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39451822/