从Python获取Java版本号

8

我需要从Python(或Bash)中获取Java版本号,例如“1.5”。

我将使用以下代码:

os.system('java -version 2>&1 | grep "java version" | cut -d "\\\"" -f 2')

但是这会返回1.5.0_30。

如果数字变为“1.10”等,它需要兼容。

我想使用cut、grep甚至是sed。它应该在一行中完成。


3
“它需要兼容” - 与什么兼容?你实际上想要实现什么目标?“它应该在一行内” - 为什么? - jonrsharpe
兼容较新的Java版本。并保持代码简洁。 - jteichert
2
你为什么认为它会在例如“1.10”中出错?你正在通过os.system运行终端命令,我认为“clean”已经过时了... - jonrsharpe
1
@jteichert 一行代码并不一定是干净的代码。 - Peter Wood
@fedorqui 我只需要主版本号和次版本号。原因是,这将进入waf脚本的构建函数中。该函数仅接受major.minor版本号(至少在我使用1.5.0时无法工作)。bld(features = 'javac jar', compat = '1.5', ... ) - jteichert
6个回答

21

Java运行时似乎会将版本信息发送到stderr。您可以使用Python的subprocess模块获取此信息:

>>> import subprocess
>>> version = subprocess.check_output(['java', '-version'], stderr=subprocess.STDOUT)

>>> print version
java version "1.7.0_79"
Java(TM) SE Runtime Environment (build 1.7.0_79-b15)
Java HotSpot(TM) Client VM (build 24.79-b02, mixed mode)

您可以使用正则表达式获取版本号:
```regex /(\d+\.){2}\d+/ ```
>>> import re
>>> pattern = '\"(\d+\.\d+).*\"'

>>> print re.search(pattern, version).groups()[0]
1.7

如果您使用的是Python 2.7版本之前的版本,请参考以下问题:subprocess.check_output() doesn't seem to exist (Python 2.6.5)

2
非常棒的一篇文章!我从中学到了很多,比我的外部awk调用要好。 - fedorqui
谢谢,一个备注:当我用check_call替换check_output时,子进程才能正常工作。我已经安装了Python 2.6。 - jteichert
@PeterWood 非常感谢您提供的针对 Python 2.7 之前版本的解决方法。 - jteichert
subprocess.Popen使用的环境是否与我的当前shell不同? 我想使用我在.bashrc中指定的JAVA_HOME路径所对应的Java版本。但是,这个命令获取到的却是另一个版本。 - jteichert
1
如果您设置了 JAVA_TOOL_OPTIONS 环境变量,那么 Java 会在实际结果之前打印出选项,这可能会破坏您后面的正则表达式。 - Fabich
显示剩余4条评论

4
考虑到这样的输出结果:
$ java -version
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

你可以像这样使用awk获取版本号:

$ java -version 2>&1 | awk -F[\"_] 'NR==1{print $2}'
1.8.0

或者,如果您仅需要前两个用 . 分隔的数字:

$ java -version 2>&1 | awk -F[\"\.] -v OFS=. 'NR==1{print $2,$3}'
1.8

这里,awk将字段分隔符设置为 "_(或 .),以便对行进行切片。然后,它打印第一行上的第二个字段(由 NR==1 指示)。通过设置 OFS,我们指定了输出字段分隔符,因此说 print $2, $3 将打印第二个字段,后跟一个 .,再后面是第三个字段。
要在Python中使用它,您需要正确转义:
>>> os.system('java -version 2>&1 | awk -F[\\\"_] \'NR==1{print $2}\'')
1.8.0
>>> os.system('java -version 2>&1 | awk -F[\\\"\.] -v OFS=. \'NR==1{print $2,$3}\'')
1.8

你不能使用 os.system() 捕获子进程的输出,因此这种方法比其他方法不太实用。 - mhawke
@mhawke 不确定为什么这里可能需要子输出。另外,正如我在Peter Wood的答案下面所说的那样,我也认为他的答案更好,因为它完全使用了Python。 - fedorqui
如果你真的想使用获得的版本号,那么孩子的输出就是必要的。 - mhawke
你真的想要避免在这里使用 os.system() 和 Awk。subprocess 的答案应该被接受。 - tripleee

1
你可以让grep处理正则表达式:

java -version 2>&1 | grep -Eow '[0-9]+\.[0-9]+' | head -1

1
你不能使用 os.system() 捕获命令的输出。相反,使用 subprocess.check_output()
>>> import subprocess
>>> java_version = subprocess.check_output(['java', '-version'], stderr=subprocess.STDOUT)
>>> java_version
'openjdk version "1.8.0_51"\nOpenJDK Runtime Environment (build 1.8.0_51-b16)\nOpenJDK 64-Bit Server VM (build 25.51-b03, mixed mode)\n'

现在您可以使用Python提取版本号,而不是通过其他命令进行管道处理(顺便提一下,这需要使用较不安全的shell=True参数来执行check_output)。
>>> version_number = java_version.splitlines()[0].split()[-1].strip('"')
>>> major, minor, _ = version_number.split('.')
>>> print 'Major: {}, Minor: {}'.format(major, minor)
Major: 1, Minor: 8

1
这是一篇旧文章,但如果有人需要它:
import subprocess
import re

javaPath = 'C:/.../java.exe'

javaInfo = subprocess.check_output(javaPath + ' -version', shell=True, stderr=subprocess.STDOUT)
javaVersion = re.search(r'"[0-9\._]*"', javaInfo.decode().split("\r")[0]).group().replace('"', '')

print(javaVersion)

0

Python

import os;

os.system("java -version 2>&1 | grep 'version' 2>&1 | awk -F\\\" '{ split($2,a,\".\"); print a[1]\".\"a[2]}'");

xxx=os.popen("java -version 2>&1 | grep 'version' 2>&1 | awk -F\\\" '{ split($2,a,\".\"); print a[1]\".\"a[2]}'").read();

print xxx
1.8

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接