1. ホーム
  2. nlp

pyhanlpレポートについて FileNotFoundError: [Errno 2] No such file or directory: '/usr/lib/jvm' エラー解決法

2022-03-01 08:35:49

pyhanlpのFileNotFoundErrorに対する解決策です。[Errno 2] そのようなファイルやディレクトリはありません: '/usr/lib/jvm' エラー

最近、HanLPを使って単語を分割することを覚え、pythonのpip経由でpyhanlpをインストールしましたが、単語を分割するためにpyhanlpをインポートしたり、hanlpコマンドを使用するとFileNotFoundErrorが報告されます。[Errno 2] No such file or directory: '/usr/lib/jvm'. Web上で同様のエラーを見つけることができないので、私は自分自身に頼るしかありません。

報告されたエラーの詳細は以下の通りです。

...
...
...
~/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 は以下のように定義されています。

# line 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)

# later omitted

そして get_jvm_path() は実際に self._methods 内のメソッドを実行します。そして self._methods の定義 (__init__() 内) を再度見てみましょう。

# line 62 or so
        # Search methods
        self._methods = (self._get_from_java_home,
                         self._get_from_known_locations)


メソッドには、このファイル内の他の2つの関数が格納されています。まず _get_from_java_home() を実行し、見つからなければ _get_from_known_locations() を実行してください。前回報告したエラーは _get_from_known_locations() で、これは _get_from_java_home() が java を見つけるのに成功しなかったことを意味します、この関数の定義を見てください。

# line 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を付けて、再ソースや再ログインすればいいのでしょう。

回避策

グローバル設定ファイル /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をインポートする前に環境変数を定義する必要がありますが、同じエラーが発生する場合は以下のようになります。


コード
# 環境変数を定義する
インポート os
os.environ['JAVA_HOME'] = '/usr/local/java/latest

# javaが見つからない問題を回避するためにhanlpを新たにインポートする。
pyhanlp を hanlp にインポートします。



ソリューションが動作する。

変更後のターミナル画面を再ソースまたは再表示して、セグメントハンプのコマンドを正常に実行することができます。

この機能は、jupyter-labでも非常によく動作します。