關于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中正常運作: