關於pyhanlp報FileNotFoundError: [Errno 2] No such file or directory: '/usr/lib/jvm'錯誤的解決
最近學習NLP用HanLP進行分詞,在python中通過pip安裝pyhanlp正常,導入pyhanlp進行分詞或使用hanlp命令都報FileNotFoundError: [Errno 2] No such file or directory: '/usr/lib/jvm',網上都沒有查到類似的錯誤,只有靠自己了。
報錯細節如下:
...
...
...
~/anaconda3/envs/tensorflow/lib/python3.7/site-packages/jpype/_jvmfinder.py in get_jvm_path(self)
160 jvm = method()
161
--> 162 # If found check the architecture
163 if jvm:
164 self.check(jvm)
~/anaconda3/envs/tensorflow/lib/python3.7/site-packages/jpype/_jvmfinder.py in _get_from_known_locations(self)
215 for home in self.find_possible_homes(self._locations):
216 jvm = self.find_libjvm(home)
--> 217 if jvm is not None:
218 return jvm
~/anaconda3/envs/tensorflow/lib/python3.7/site-packages/jpype/_jvmfinder.py in find_possible_homes(self, parents)
120 for childname in sorted(os.listdir(parent)):
121 # Compute the real path
--> 122 path = os.path.realpath(os.path.join(parent, childname))
123 if path in homes or not os.path.isdir(path):
124 # Already known path, or not a directory -> ignore
FileNotFoundError: [Errno 2] No such file or directory: '/usr/lib/jvm'
原因分析:
可以看到是在執行_jvmfinder.py文件的find_possible_homes遇到的問題,於是打開這個文件去看了報錯文件的源代碼。我們在調用hanlp時將運行_jvmfinder.py的get_jvm_path()函數來獲取系統的java路徑,get_jvm_path定義如下
# 第147行
def get_jvm_path(self):
"""
Retrieves the path to the default or first found JVM library
Returns:
The path to the JVM shared library file
Raises:
ValueError: No JVM library found or No Support JVM found
"""
jvm_notsupport_ext = None
for method in self._methods:
try:
jvm = method()
# If found check the architecture
if jvm:
self.check(jvm)
# 後面 略
而get_jvm_path()實際上是運行self._methods中的方法,我們再看self._methods的定義(__init__()中):
# 第62行左右
# Search methods
self._methods = (self._get_from_java_home,
self._get_from_known_locations)
_methods中存的是本文件的另外兩個函數,先運行_get_from_java_home(),如果沒找到再運行_get_from_known_locations()。前面我們報錯的是_get_from_known_locations(),那也就是說_get_from_java_home()沒有成功找到java,來看這個函數的定義:
# 第186行
def _get_from_java_home(self):
"""
Retrieves the Java library path according to the JAVA_HOME environment
variable
Returns:
The path to the JVM library, or None
"""
# Get the environment variable
java_home = os.getenv("JAVA_HOME")
if java_home and os.path.exists(java_home):
# Get the real installation path
java_home = os.path.realpath(java_home)
# Cygwin has a bug in realpath
if not os.path.exists(java_home):
java_home = os.getenv("JAVA_HOME")
# Look for the library file
return self.find_libjvm(java_home)
這個函數主要通過獲取系統環境變量JAVA_HOME來得到java的地址。可是命令行中運行java正常,爲什麼沒找到這個環境變量呢? 重新查看一下配置文件/etc/profile中java環境變量的配置,如下
# set java path
JAVA_HOME=/usr/local/java/latest
export PATH=${JAVA_HOME}/bin:${PATH}
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
平時在命令行中能直接運行java,是因爲java所在的bin目錄被添加到PATH,且由export PATH後作爲環境變量生效。但是JAVA_HOME只是作爲普通變量,使用os.getenv()的時候獲取環境變量時找不到JAVA_HOME,所以推測應該只要將JAVA_HOME前面添加export,然後重新source或重新登錄即可。
解決辦法:
在全局配置文件/etc/profile或個人配置文件~/.bashrc或~/.bash_profile中添加export JAVA_HOME即可,如下是我的/etc/profile的設置:
# set java path
export JAVA_HOME=/usr/local/java/latest
export PATH=${JAVA_HOME}/bin:${PATH}
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
其他注意事項:如果使用PyCharm遠程調試,若遇到同樣報錯,需要在導入pyhanlp前先設置環境變量,如下
# 設置環境變量
import os
os.environ['JAVA_HOME'] = '/usr/local/java/latest'
# 再導入hanlp 即可避免無法找到java的問題
import pyhanlp as hanlp
解決效果:
修改後重新source或重新開一個終端窗口,可以成功運行hanlp segment命令
也可以在jupyter-lab中正常運行: