如何使用Python创建独立于语言的库?

时间:2017-06-05 17:27:55

标签: python api

如果我在Python中创建一个包,那么另一个Python用户可以导入该包并与之接口。

如何创建一个包,以便其他用户调用该库的语言无关紧要?

我可以指定输入和输出文件格式,以便另一种语言可以通过仅提供输入文件和读取输出文件来与我的Python代码进行交互。但是,创建输入和输出文件在计算上非常昂贵。有更简单的解决方案吗?

7 个答案:

答案 0 :(得分:7)

如果您希望其他语言能够直接使用您的库 (不使用任何类型的远程服务或IPC的东西,这是一个完全不同的鱼),您需要写语言绑定,意味着他们在目标语言中调用了一个层来调用你的包。有许多工具包可用于创建它,但如果您希望能够从更高级别的脚本语言(如Python)调用C或C ++库,通常会执行此类操作。例如,在C中存在SWIG项目,以帮助从Python,PHP,Ruby等调用C语言。

这个页面会给你一堆介绍链接,说实话,这是一个很难和很难的话题。我自己只用C到Python做过。 https://wiki.python.org/moin/IntegratingPythonWithOtherLanguages

答案 1 :(得分:3)

通过像http这样的通用协议提供API,并使用通用的调用和响应格式(如REST服务)可能就是您想要做的。有很多资源可以帮助您开始使用python编写REST Web服务,如下所示:

https://blog.miguelgrinberg.com/post/designing-a-restful-api-with-python-and-flask

如果你想让它保持在本地机器上,并提供你在本地程序中使用的python功能,python.org在这里给你一个入门读物:

https://docs.python.org/2/extending/embedding.html

答案 2 :(得分:3)

在一般情况下,两种不同的语言不能生活在同一个过程中。所以你必须通过进程间通信(IPC)让一种语言调用另一种语言。

最简单且通常有效的方法是通过calee" library"的输入/输出。它通常具有某种序列化开销,但在典型的matlab / python交互中,它应该是不明显的。

在这种配置中,最慢的部分是python进程的启动,可以通过在两次调用之间保持相同的进程处于活动状态来抑制它。

这里有一个ipc的例子,它是python中的一个主程序(但可以用任何语言编写)和python中的一个库,使用stdin / stdout和json作为序列化

#main program in foreign language

import mylibwrapper

print(mylibwrapper.call("add",[1,2]))

mylibwrapper.exit()
#mylibwrapper.py supposed written in foreign language
import subprocess
import json

process = subprocess.Popen([
    "python3",
     "mylib.py"],
    stdin = subprocess.PIPE,
    stdout = subprocess.PIPE,
    encoding = "utf8")

def call(name,args):
  process.stdin.write(json.dumps([name,args]))
  process.stdin.write("\n")
  process.stdin.flush()
  result = process.stdout.readline()
  return(result)
def exit():
  process.terminate()
#mylib.py

import json, sys

def add(arg1,arg2):
  return arg1 + arg2

if __name__ == "__main__":

  for line in sys.stdin:
    name, args = json.loads(line)
    function = { "add" : add }[name]
    sys.stdout.write(json.dumps(function( *args)))
    sys.stdout.write("\n")
    sys.stdout.flush()

答案 3 :(得分:2)

@ bluprince13没有这样的方法可以从每种语言调用库,至少不能直接使用包装器代码。 Windows上的COM接口已经关闭,然后可以被大多数程序(例如Excel,MATLAB,JAVA)导入,但这是一个巨大的痛苦。

当你说读/写是一项昂贵的操作时,你不能使用Pandas read_csvto_csv函数 - 它们是超快速(C ++)实现。更快速的是二进制HDF5文件,尽管对于大多数http://pandas.pydata.org/pandas-docs/version/0.20/io.html read_hdfto_hdf用户来说,它们更难以使用,这些用户可以使用大量语言https://en.wikipedia.org/wiki/Hierarchical_Data_Format。使用输入和输出文件将使您的程序更加便携。

使用嵌入式Python(已编译),您可以在本帖末尾的DropBox链接中使用您在.py表单中创建的任何Python函数(embedpython.exe)以及所有文件在那里的zip中,这可能是你最好,最简单,最快的路径 - 源代码/用法参考:Embedded Python does not work pointing to Python35.zip with NumPy - how to fix? FAR是让你的代码在任何系统上兼容,并在你的Python之间切换的最简单方法脚本很简单(当你调用不同的库时,整个包必须在子文件夹中可用)。在Anaconda Python安装中,文件将位于相应的已安装包文件夹中,通常为C:\Anaconda3\Lib\site-packages\ [packageName] \;典型的Python安装位于C:\Python\Lib\site-packages\ [packageName] \)。否则,从安装了Python的命令提示符cd\开始,dir /s site-packages将找到该位置。然后,将每个包的整个安装目录放在“extension_modules”目录下。所以它看起来像extension_modules\numpy\extension_modules\pandas\,以及您要导入的所有库(以及包依赖的库)。

以下是如何使用EXE调用相应语言的一些示例:JAVA:Process process = new ProcessBuilder("C:\\PathToExe\\embedpython.exe","pyscript","pyfunction","input_param1","input_param2").start(); MATLAB:system('"C:\PathToExe\embedpython.exe" pyscript pyfunction input_param1 input_param2'); VBA:Call Shell("C:\PathToExe\embedpython.exe" "pyscript" "pyfunction" "param1" "param2", vbNormalFocus) C ++:How to call an external program with parameters? .NET C#:How to pass parameters to an exe?如您所见,列表一直在继续......几乎任何语言都可以调用EXE文件。当然,您需要最高性能,但要获得所有语言的兼容性,您必须以某种方式妥协。但是使用上述建议,只要.py函数得到优化,您的性能仍然会很好。

让每个人的生活更轻松这里是编译版x64 Python 3.5 Windows NumPy SciPy和Pandas英特尔MKL包括:https://www.dropbox.com/sh/2smbgen2i9ilf2e/AADI8A3pCAFU-EqNLTbOiUwJa?dl=0

如果您是Windows用户,请下载以上内容并将您的.py脚本放在您要分发的位置,以及\ extension_modules \ [package_name]中的依赖库,您的代码将是没有麻烦。您没有指定是否在Linux下使用它,因此我的Windows解决方案是您“使用任何语言”的问题,需要对其他编程语言的了解最少。

答案 4 :(得分:2)

您可以使用Cython to relatively easily extend your python code so that it can be compiled as a C library。大多数情况下,这只涉及将def关键字替换为cdef public,以用于要公开的函数,并注释变量类型。

以下是此类Cython代码的示例:

cdef public void grail(int num):
    printf("Ready the holy hand grenade and count to %i", num) 

此时,许多语言都有Foreign Function Interfaces (FFI)到C代码。

答案 5 :(得分:1)

正如已经多次提到的那样 - 其中一种方法是创建REST API并通过HTTP发送输入和输出。

但是,还有另一种选择更为复杂。您可以使用CORBA(公共对象请求代理体系结构)。在python omniORB中有一个CORBA实现。 CORBA允许在用各种语言编写的应用程序之间进行接口。

在网上使用CORBA和python有很多例子。

答案 6 :(得分:1)

与Nurzhan上面提到的关于CORBA的类似精神,您可以使用OPC UA:https://en.m.wikipedia.org/wiki/OPC_Unified_Architecture

这是一种面向通过服务器到客户端通信进行设备控制的架构,但可能适合您的需求。在我的工作中,我们使用了许可的C / C ++(统一自动化和Java sdks(prosys),探索了Python选项以及来自PLC的嵌入式解决方案,并且可以很好地进行跨层通信。

Web中有几个用于Python UA的OPC UA的开源项目,例如: freeopcua。