精通 Oracle+Python,第 9 部分:Jython 和 IronPython — 在 Python 中使用 JDBC 和 ODP.NET

作者:Przemyslaw Piotrowski

这一部分将介绍 Python 的两个最常用的开发环境 — Java 和 .NET,以及这些平台的 Python 原生实现。

2011 年 12 月发布

red_arrow_box.gif  参见系列目录

 
成功的编程语言总是会成为顶级开发平台。对于 Python 和世界上的两个顶级编程环境 Java 和 Microsoft .NET 来说的确如此。

虽然人们因为 Python 能够快速组装不同的软件组件而常常称其为“粘合语言”,但已出现了对它的原生实现的需求。1997 年,麻省理工学院的研究生 Jim Hugunin 启动了 Jython 项目,即用 Java 实现 Python,该项目取得了非凡的成果,让我们可以在高效的 Java 虚拟机 (JVM) 上运行一种动态的高级语言。此后,Jython 吸引了众多参与者。Oracle WebLogic Server 用户可能已经熟悉此工具,它包括在 WebLogic 软件包中,用于编写脚本。截至本文撰写时,最新的 Jython 版本是 2.5.2。

Hugunin 并没有就此止步。人们曾一度认为不可能在 .NET 核心的通用语言运行时 (CLR) 上实现动态语言。但在 2004 年,当时就职于 Microsoft 的 Hugunin 与一个小型团队一起创建了 IronPython 项目,此项目不仅颠覆了传统观念,而且在某些情况下还表现得优于 C 实现。虽然此项目不再由 Microsoft 领导,但它仍在开展,并于 2011 年 10 月发布了 IronPython 2.7.1。

在本文中,您将了解如何将这些 Python 方言与 Oracle 数据库及其无处不在的访问驱动程序(JDBC 和 ODP.NET)一起结合使用。获取有关连通性、查询实践和驱动程序细节的基本知识之后,您便能够将 Python 插入到您喜欢的任何环境中,从而借助 JVM 和 CLR 的优势实现极速开发。

请注意,您不再仅限于使用命令行。市场上提供了多种 IDE,其中包括 NetBeans IDE、适用于 Jython 的 Eclipse(具有 PyDev 扩展)和适用于 IronPython 的 SharpDevelop。此外,因为这是最简单的 Python,所以您无疑可以利用动态解释器,这可让您测试库和模块。

Jython 和 JDBC

通过从 www.jython.org 获得的 JAR 可执行包,可以非常简单地安装 Jython。下载 jython_installer_2.5.2.jar 之后,只需执行存档文件:

C:\java -jar jython_installer-2.5.2.jar

 mastering-oracle-python-providers-f1

图 1 Jython 安装屏幕

在目标 Jython 目录下,您可以找到 jython.jar 文件以启动解释器。除了 CLASSPATH 之外,在运行过程中还使用另一个环境变量 JYTHONPATH。一个最有用的选项是能够在运行之后检查代码(-i 开关),这样您可以查看各种变量、重新声明部分代码和重新运行。

用法: jython [option] ... [-c cmd | -m mod | file | -] [arg] ...
选项和参数:
-c cmd   :程序作为字符串传入(终止选项列表)
-Dprop=v :将“prop”属性的值设为“v”
-C codec :从控制台读取时,使用不同的编解码器。
-h     :打印这条帮助信息并退出(--help 作用相同)
-i     :运行脚本后进行交互式检查
              并强制提示,即时 stdin 看上去不是个终端
-jar jar :在 jar 文件中从 __run__.py 读取程序
-m mod   :将库模块作为一个脚本运行(终止选项列表)
-Q arg   :分支选项:-Qold(默认)、-Qwarn、-Qwarnall、-Qnew
-S     :不要在初始化时暗示“导入站点”
-u     :未缓存的二进制 stdout 和 stderr
-v     :详细模式(跟踪导入语句)
-V     :打印 Python 版本号并退出(--version 作用相同)
-W arg   :警告控制(参数为 action:message:category:module:lineno)
file   :从脚本文件读取的程序
-      :从 stdin 读取的程序(默认;如果 tty,则为交互模式)
arg ...  :在 sys.argv[1:] 中传递给程序的参数
其他环境变量:
JYTHONPATH:默认模块搜索路径前面的以“;”分隔的目录列表。
             结果为 sys.path。

虽然标准 JDBC API 基于 java.sql 包,但 Oracle 提供自己的模块以便扩展基本功能和提供到 Oracle 数据类型的映射:oracle.jdbc 和oracle.sql。本文涵盖所有这些内容,但如果您需要任何更多信息,请参阅 Oracle 数据库 JDBC 开发人员指南

至于客户端连通性,您可以随意选择原生 Java 实现(JDBC 瘦驱动程序 — 完全跨平台,封装在一个 JAR 压缩文件中)或 Oracle 调用接口 (OCI) — 与通过 C 进行连接所用的客户端完全相同。(请注意,OCI 依赖于 Oracle Client 或 Oracle Instant Client。)

不需要初始设置,只有一行代码的文本文件(如下所示)使用瘦驱动程序实现基本 JDBC 连通性。您只需确保 ojdbc6.jar 在 CLASSPATH 或 JYTHONPATH 中,以便可以解析连接驱动程序。

conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE", "hr", "hr")

查询数据库并不比这难多少。只需具备基本 Java 知识便足以轻松地使用 Jython。一切都非常简练。

from java.sql import DriverManager

conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE", "hr", "hr")
stmt = conn.createStatement()
rs = stmt.executeQuery("select * from employees order by last_name")

emp = {}
while rs.next():
  emp[rs.getString(4)] = {
       'name': "%s, %s" % (rs.getString(3), rs.getString(2)),  
       'email': rs.getString(4),
       'salary': rs.getInt(8)
  }
  print "%s, %s (%s)" % (rs.getString(3), rs.getString(2), rs.getString(4))

rs.close()
stmt.close()
conn.close()

我们不仅受益于简练、快速的实现,而且还能够以交互方式运行此脚本,就像您使用 Python 时那样。图 2 说明我们如何从常规程序执行中跳到 Jython shell 中,这时我们可检查现有对象并对它们执行进一步操作 — 通过 Python 或原生 Java 库。

 mastering-oracle-python-providers-f2

图 2 分别以标准模式和交互模式运行脚本

如果您要使用 OCI 取代瘦驱动程序,则需要更改提供给 DriverManager 的连接字符串,如下所示。(OCI 的明显优势在于连接池、透明应用程序故障切换和客户端结果缓存等固有特性。)

conn = DriverManager.getConnection("jdbc:oracle:oci:@localhost:1521:XE", "hr", "hr")

OracleDataSource 支持原生数据类型、性能改进和更好的兼容性。使用 Jython 之后,您可以使用用于 Java 的几乎所有的库,oracle.jdbc.pool.OracleDataSource 也不例外。

此示例通过连接异常处理完善了常规 JDBC,该异常处理可捕获 java.sql.SQLException 错误,同时建立到 Oracle 数据源的新连接。

import sys
import java.sql.SQLException
from oracle.jdbc.pool import OracleDataSource

cs = "jdbc:oracle:thin:@localhost:1521:XE"

ods = OracleDataSource()
ods.setURL(cs)
ods.setUser("hr")
ods.setPassword("hr")
try:
  conn = ods.getConnection()
except java.sql.SQLException, e:
  print "Problem connecting to \"%s\"" % cs
  sys.exit()

stmt = conn.createStatement()
rs = stmt.executeQuery("select * from departments order by 2")

while rs.next():
  print rs.getString(2)

rs.close()
stmt.close()
conn.close()

对于 Java 应用程序的快速原型开发以及将不同的软件组件粘合在一起来说,Jython 是极好的选择。但是,Jython 与众不同之处不仅在于极高的开发速度 — 动态自省、简练的语法和丰富的编程语言只是一些基本特性。真正的价值来自可用于两个平台的丰富的库(无论它们源于何种语言)。您可以将 Jython 用于 JEE 基础架构并在 Oracle WebLogic Server 上部署 Django,将 Jython 与 Jasper Reports 结合使用以实现灵活的 BI 解决方案,或者在您的下一个 Java 项目中利用 Python 索引 (PyPI) 中提供的 17,000 多个程序包之一。

IronPython 和 ODP.NET

Python 的“开箱即用”理念通过 IronPython 获得全新含义,IronPython 为您提供对丰富的 .NET 库的访问。从可访问性 和各种 Microsoft 容器直到庞大的系统 命名空间,基于 .NET 的 IronPython 使您有各种机会采用喜爱的编程语言进行编码。因为我们的系列文章仅面向数据库,所以本文将着重介绍 Windows Presentation Foundation 和 Oracle Data Provider 库。

与 Jython 相同,最重要的部分是 IronPython 可执行文件。它以四个二进制文件的形式提供:

  • ipy.exe
  • ipy64.exe
  • ipyw.exe
  • ipyw64.exe

其中“w”后缀表示“窗口式”应用程序,“64”表示在 64 位架构上运行。即使 IronPython 主要针对 Microsoft Windows 平台,但 .NET 的 Linux 实现 (Mono) 用户也可以使用它的一些功能。

用法:ipy.exe 用法:ipy [options] [file.py|- [arguments]]

选项:
 -3                          Python 3.x 的不兼容性警告
 -c cmd                      程序作为字符串传入(终止选项列表)
 -D                          启用应用程序调试
 -E                          忽略环境变量
 -h                          显示用法
 -i                          运行脚本后进行交互式检查
 -m module                   将库模块作为一个脚本运行
 -O                          生成优化的代码
 -OO                         删除文档字符串并应用 -O 优化
 -Q arg                      分支选项:-Qold(默认)、-Qwarn、-Qwarnall、-Qnew
 -s                          不要向 sys.path 添加用户站点目录
 -S                          不要在初始化时暗示“导入站点”
 -t                          发出有关 Tab 键使用不一致的警告
 -tt                         发出有关 Tab 键使用不一致的错误
 -u                          未缓存的 stdout 和 stderr
 -v                          详细模式(跟踪导入语句)(并且 PYTHONVERBOSE=x)
 -V                          打印版本号并退出
 -W arg                      警告控制(参数为 action:message:category:module:lineno)
 -x                          跳过源代码的第一行
 -X:AutoIndent               在 REPL 循环中启用自动缩进功能
 -X:ColorfulConsole          启用 ColorfulConsole
 -X:CompilationThreshold  解释器开始编译前的迭代数
 -X:Debug                    启用应用程序调试(优于 -D)
 -X:EnableProfiler           在编译器中启用分析支持
 -X:ExceptionDetail          启用 ExceptionDetail 模式
 -X:Frames                   启用基本的 sys._getframe 支持
 -X:FullFrames               启用 sys._getframe,可以访问本地
 -X:GCStress                 指定 GC 压力级别(可以收集每条语句的一代)
 -X:LightweightScopes        生成可以收集垃圾的优化范围
 -X:MaxRecursion             设置最大递归级别
 -X:MTA                      在多线程单元中运行
 -X:NoAdaptiveCompilation 禁用自适应编译
 -X:NoDebug <regex>          提供不应在调试模式中发出的文件的正则表达式
 -X:PassExceptions           不要捕捉脚本代码未处理的一场
 -X:PrivateBinding           启用对私有成员的绑定
 -X:Python30                 启用可用的 Python 3.0 特性
 -X:ShowClrExceptions        显示 CLS 异常信息
 -X:TabCompletion            启用 TabCompletion 模式
 -X:Tracing                  即使在调用 sys.settrace 前启用跟踪所有方法的支持

环境变量:
 IRONPYTHONPATH       搜索模块的路径
 IRONPYTHONSTARTUP 启动模块

与 Jython 相比,IronPython 的交互式 shell 更丰富。它支持 Tab 键自动完成功能、语法着色以及与框架的更紧密集成,并附带高级调试和分析机制。

mastering-oracle-python-providers-f3 

图 3 IronPython 交互式 shell,在向 Oracle.DataAccess 库中添加引用时实现动态自省、高亮显示和 Tab 键完成功能

可以采用多种方法加载 .NET 组合件;两种最常用和建议的方法是:

  • clr.AddReference — 接受直接对象引用(例如“System.Random”)
  • clr.AddReferenceToFileAndPath — 使用直接路径解析库引用(例如“D:/oraclexe/app/oracle/product/11.2.0/server/odp.net/bin/4/Oracle.DataAccess.dll”)

CLR 是适用于 .NET 的虚拟机,在 IronPython 中作为 clr 模块引用。IronPython 和 .NET 组合件之间的所有交互都通过此库处理。

可以轻松地通过 ipy 解释器添加外部组合件,如下所示:

>>> import clr
>>> clr.AddReference(“Oracle.DataAccess”)
>>> import Oracle.DataAccess


为了确保导入正确的版本,我们可以直接引用文件:

>>> import clr
>>> clr.AddReferenceToFileAndPath(““D:/oraclexe/app/oracle/product/11.2.0/server/odp.net/bin/4/Oracle.DataAccess.dll””)
>>> import Oracle.DataAccess


最基本的示例仅需要从 Oracle.DataAccess.Client 命名空间导入一个对象。代码本身类似于我们先前用于 Jython 的代码。以下示例将遍历所有部门并将它们打印出来。


import clr
clr.AddReference("Oracle.DataAccess")
from Oracle.DataAccess.Client import OracleConnection

conn = OracleConnection("User Id=hr;Password=hr;Data Source=XE")
conn.Open()
cmd = conn.CreateCommand()
cmd.CommandText = "select * from departments order by 1"

reader = cmd.ExecuteReader()
if reader.HasRows:
  while reader.Read():
       dept = {
       'id': reader.GetDecimal(reader.GetOrdinal("DEPARTMENT_ID")),
       'name': reader.GetString(reader.GetOrdinal("DEPARTMENT_NAME"))
       }
       print "Department #%s: %s" % (dept['id'], dept['name'])

conn.Close()

使用 .NET 而不创建窗口式应用程序似乎并不十分合适,因此让我们尝试利用一些 GUI 控件并通过网格组件展示效果。为此,我们将在连接数据库时使用 .NET 库中的两个重要对象:DataSet 和 OracleDataAdapter。为了呈现窗口并放置组件,我们将使用System.Windows.Forms 和 System.Drawing 库。

import clr
clr.AddReference("Oracle.DataAccess")
clr.AddReference("System.Data")
clr.AddReference("System.Drawing")
clr.AddReference("System.Windows.Forms")

from System.Drawing import Size
from System.Data import DataSet
from Oracle.DataAccess.Client import OracleConnection, OracleDataAdapter
from System.Windows.Forms import Application, DataGridView, DockStyle, Form

form = Form(Size = Size(800, 600))
form.Text = "Mastering Oracle+Python, Part 9: ODP.NET with IronPython"

conn = OracleConnection("User Id=hr;Password=hr;Data Source=XE")
conn.Open()
oda = OracleDataAdapter()
ds = DataSet()

cmd = conn.CreateCommand()
cmd.CommandText = "select * from employees order by 1"
oda.SelectCommand = cmd
oda.Fill(ds)
conn.Close()

grid = DataGridView(DataSource = ds.Tables[0], AutoSize = True, Dock = DockStyle.Fill)
form.Controls.Add(grid)
Application.Run(form)

产生的应用程序将如图 4 中所示。

mastering-oracle-python-providers-f4 

图 4 IronPython 应用程序通过 OracleDataAdapter 和 DataGridView 与 Oracle Database XE 交互。

正如我们刚刚展示的那样,通过 IronPython 与 .NET 框架交互如同使用 C# 或 Visual Basic 等原生 CLR 原生语言一般顺畅。

通过打包的 ipy.exe 工具和 pyc.py 编译脚本(位于 Tools\Scripts 目录下),可以非常顺畅地将 IronPython 程序打包成 .exe 二进制文件。为了将脚本变成可执行二进制文件,您只需提供输出的名称和类型,如下所示。

C:\IronPython-2.7>ipy Tools\Scripts\pyc.py /out:GridView /target:exe /main:gridview.py
Input Files:
Output:
       GridView
Target:
       ConsoleApplication
Platform:
       ILOnly
Machine:
       I386
Compiling...
Saved to GridView

在编译完成后,我们就在当前目录中拥有了 GridView.exe 和 GridView.dll 文件。现在,谁会说您不能将 Python 程序编译为可执行文件?

冰山一角

Jython 和 IronPython 只是在其他编程环境中使用 Python 语法的两个示例。我们已了解 Python 的动态特性能够与静态类型的 JVM 和 CLR 很好地相融(尽管存在其他设想)。

另一个有用的实现是 PyPy,这是采用静态类型 Python 方言(名为 RPython)编写的 Python 实现。PyPy 附带了一个实时编译器,它尝试获得最高性能,同时保持符合原生 Python 实现的要求。

ctypes 提供与 C 语言的兼容性,因此您可以直接通过 Python 调用共享库和 DLL。无论是 Windows 上的 windll.kernel32 还是 Linux 上的 libc.so.6,ctypes,都会为您提供到其中所有函数的“Python 式”接口。在 Python 中使用 Pro*C?对于 ctypes 来说不成问题。

在本部分中,我们介绍了在 Jython 下使用 JDBC 以及在 IronPython 下使用 ODP.NET 与 Oracle 数据库交互。我们了解了如何针对这些平台从 Java 和 C# 顺畅过渡到 Python 实现。采用 JVM 和 .NET 必须提供的新平台以及内容广泛的库之后,您在 Python 技能方面的投入越多,获得的回报就会越丰厚。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值