GraalVM 中的 运行 Python - `import requests` 失败并出现异常:您需要安装 charset_normalizer 或 chardet(请求初始化失败)

run Python in GraalVM - `import requests` fails with Exception: You need either charset_normalizer or chardet installed (requests init failure)

我尝试在 GraalVm 中 运行 Python 脚本,但它在

上失败了
import requests

这似乎是 GraalVM 的问题,因为脚本可以正常工作 python3

Java代码:

import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Source;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Paths;

public class RunPython4 {
    public static String PYTHON = "python";
    // venv/**/* must be included into resources in pom.xml
    private static String VENV_EXECUTABLE = RunPython4.class.getClassLoader().getResource(Paths.get("venv", "bin", "graalpython").toString()).getPath();
    private static String SOURCE_FILE_NAME = "health.py";

    public static void log(String s){
        System.out.println(s);
    }

    public static void main(String[] args) {
        log("Hello Java!");
        log(System.getProperty("java.version"));
        log(System.getProperty("java.runtime.version"));

        String pyFilename = "./health.py";

        try (Context context = Context.newBuilder("python").
                allowAllAccess(true).
                option("python.ForceImportSite", "true").
                option("python.Executable", VENV_EXECUTABLE).
                build();) {
            context.eval(PYTHON, "print('Hello Python!')");

            context.eval(PYTHON, "import sys; print(sys.version)");

            //4
            try(BufferedReader br = new BufferedReader(new FileReader(pyFilename))) {
                int i = 0;
                for(String line; (line = br.readLine()) != null; ) {
                    i++;
                    log(""+i+": "+line);
                    context.eval("python", line);
                }
            }catch ( IOException e){
                log("IOException "+e);
            }

输出:

Hello Java!
11.0.11
11.0.11+8-jvmci-21.1-b05
Hello Python!
3.8.5 (Fri Jun 25 17:55:09 CST 2021)
[Graal, GraalVM CE, Java 11.0.11]
1: # Checking subgraph health v1.1
2: # https://thegraph.com/docs/deploy-a-subgraph#checking-subgraph-health
3: 
4: import requests
Exception in thread "main" Exception: You need either charset_normalizer or chardet installed
    at org.graalvm.sdk/org.graalvm.polyglot.Context.eval(Context.java:379)
    at RunPython4.main(RunPython4.java:54)

Process finished with exit code 1

我搜索得更深,"You need either charset_normalizer or chardet installed"是来自

的字符串

https://github.com/psf/requests/blob/master/requests/__init__.py#L57-L85

def check_compatibility(urllib3_version, chardet_version, charset_normalizer_version):
    urllib3_version = urllib3_version.split('.')
    assert urllib3_version != ['dev']  # Verify urllib3 isn't installed from git.

    # Sometimes, urllib3 only reports its version as 16.1.
    if len(urllib3_version) == 2:
        urllib3_version.append('0')

    # Check urllib3 for compatibility.
    major, minor, patch = urllib3_version  # noqa: F811
    major, minor, patch = int(major), int(minor), int(patch)
    # urllib3 >= 1.21.1, <= 1.26
    assert major == 1
    assert minor >= 21
    assert minor <= 26

    # Check charset_normalizer for compatibility.
    if chardet_version:
        major, minor, patch = chardet_version.split('.')[:3]
        major, minor, patch = int(major), int(minor), int(patch)
        # chardet_version >= 3.0.2, < 5.0.0
        assert (3, 0, 2) <= (major, minor, patch) < (5, 0, 0)
    elif charset_normalizer_version:
        major, minor, patch = charset_normalizer_version.split('.')[:3]
        major, minor, patch = int(major), int(minor), int(patch)
        # charset_normalizer >= 2.0.0 < 3.0.0
        assert (2, 0, 0) <= (major, minor, patch) < (3, 0, 0)
    else:
        raise Exception("You need either charset_normalizer or chardet installed")

很明显 requests init 故障转移 charset_normalizer_version 可能未定义

https://github.com/psf/requests/blob/master/requests/__init__.py#L47

try:
    from charset_normalizer import __version__ as charset_normalizer_version
except ImportError:
    charset_normalizer_version = None

requests 包当然存在

问题是,我安装 requests 使用系统 python 而不是 graalpython -m ginstall install requests

有些包编译起来很复杂,请放心使用准备好的(预编译?/固定的)包。

可运行代码位于 https://github.com/paulvi/graalpython-java-template