關於pyhanlp報FileNotFoundError: [Errno 2] No such file or directory: '/usr/lib/jvm'錯誤的解決

關於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中正常運行:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章