解决Julia使用PyPlot库出现ERROR: ArgumentError: hasproperty of NULL PyObject问题

解决Julia使用PyPlot库出现ERROR: ArgumentError: hasproperty of NULL PyObject问题

问题描述

Julia安装完成PyPlot后,在使用时遇到如下问题:

$ julia
julia> using Pkg
julia> Pkg.add("PyPlot")
using PyPlot,Random
[ Info: Precompiling PyPlot [d330b81b-6aea-500a-939a-2ce795aea3ee]
ERROR: InitError: PyError (PyImport_ImportModule

The Python package matplotlib could not be imported by pyimport. Usually this means
that you did not install matplotlib in the Python version being used by PyCall.

PyCall is currently configured to use the Python version at:

/usr/bin/python3

and you should use whatever mechanism you usually use (apt-get, pip, conda,
etcetera) to install the Python package containing the matplotlib module.

One alternative is to re-configure PyCall to use a different Python
version on your system: set ENV["PYTHON"] to the path/name of the python
executable you want to use, run Pkg.build("PyCall"), and re-launch Julia.

Another alternative is to configure PyCall to use a Julia-specific Python
distribution via the Conda.jl package (which installs a private Anaconda
Python distribution), which has the advantage that packages can be installed
and kept up-to-date via Julia.  As explained in the PyCall documentation,
set ENV["PYTHON"]="", run Pkg.build("PyCall"), and re-launch Julia. Then,
To install the matplotlib module, you can use `pyimport_conda("matplotlib", PKG)`,
where PKG is the Anaconda package that contains the module matplotlib,
or alternatively you can use the Conda package directly (via
`using Conda` followed by `Conda.add` etcetera).

) <class 'ModuleNotFoundError'>
ModuleNotFoundError("No module named 'matplotlib'",)

Stacktrace:
 [1] pyimport(::String) at /home/brainiac/Program/julia/julia-1.5.3/julia-depot/packages/PyCall/BD546/src/PyCall.jl:550
 [2] pyimport_conda(::String, ::String, ::String) at /home/brainiac/Program/julia/julia-1.5.3/julia-depot/packages/PyCall/BD546/src/PyCall.jl:708
 [3] pyimport_conda at /home/brainiac/Program/julia/julia-1.5.3/julia-depot/packages/PyCall/BD546/src/PyCall.jl:707 [inlined]
 [4] __init__() at /home/brainiac/Program/julia/julia-1.5.3/julia-depot/packages/PyPlot/XHEG0/src/init.jl:179
 [5] _include_from_serialized(::String, ::Array{Any,1}) at ./loading.jl:697
 [6] _require_from_serialized(::String) at ./loading.jl:749
 [7] _require(::Base.PkgId) at ./loading.jl:1040
 [8] require(::Base.PkgId) at ./loading.jl:928
 [9] require(::Module, ::Symbol) at ./loading.jl:923
during initialization of module PyPlot

如不解决此问题,会在后续使用PyPlot时,报“ERROR: ArgumentError: hasproperty of NULL PyObject”错误:
错误描述

具体描述如下:

julia> using Random, PyPlot
julia> function f()
	       Random.seed!(1)
	       r = rand(50)
	       @show sum(r)
	       display(transpose(r))
	       print(transpose(r))
	       plot(r)
       end

f (generic function with 1 method)
julia> f()
sum(r) = 23.134209483707394
1×50 LinearAlgebra.Transpose{Float64,Array{Float64,1}}:
 0.236033  0.346517  0.312707  0.007909280.524975  0.241591  0.884837
[0.23603334566204692 0.34651701419196046 0.3127069683360675 0.00790928339056074 0.4886128300795012 0.21096820215853596 0.951916339835734 0.9999046588986136 0.25166218303197185 0.9866663668987996 0.5557510873245723 0.43710797460962514 0.42471785049513144 0.773223048457377 0.2811902322857298 0.20947237319807077 0.25137920979222494 0.02037486871266725 0.2877015122756894 0.859512136087661 0.07695088688120899 0.6403962459899388 0.8735441302706854 0.27858242002877853 0.7513126327861701 0.6448833539420931 0.07782644396003469 0.8481854810000327 0.0856351682044918 0.5532055454580578 0.46335024592359875 0.18582130997265378 0.11198087695816716 0.976311881619359 0.051614620674327094 0.5380295812064833 0.4556920516275036 0.2793951106725605 0.17824610354168602 0.5489828719625274 0.37097066286146885 0.8941659192657594 0.6480537482231894 0.4170393538841062 0.14456554241360564 0.6224031828206811 0.8723344353741975 0.5249746566167794 0.24159060827129641 0.8848369255734128]ERROR: ArgumentError: hasproperty of NULL PyObject
Stacktrace:
 [1] pyhasproperty(::PyCall.PyObject, ::String) at /home/brainiac/Program/julia/julia-1.5.3/julia-depot/packages/PyCall/BD546/src/PyCall.jl:363
 [2] hasproperty at /home/brainiac/Program/julia/julia-1.5.3/julia-depot/packages/PyCall/BD546/src/PyCall.jl:369 [inlined]
 [3] plot(::Array{Float64,1}; kws::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /home/brainiac/Program/julia/julia-1.5.3/julia-depot/packages/PyPlot/XHEG0/src/PyPlot.jl:174
 [4] plot at /home/brainiac/Program/julia/julia-1.5.3/julia-depot/packages/PyPlot/XHEG0/src/PyPlot.jl:174 [inlined]
 [5] f() at ./REPL[10]:7
 [6] top-level scope at REPL[11]:1

问题定位

主要问题在于调用matplotlib问题,导致PyCall库的编译出现错误,使PyPlot不能正常使用。

尝试方法

看到报错信息中set ENV["PYTHON"] to the path/name of the python executable you want to use, run Pkg.build("PyCall"),因此首先尝试了此方法:

# 打印PyCall构建DEBUG信息
julia> ENV["PYCALL_DEBUG_BUILD"] = "yes"
# 修改python执行路径
julia> ENV["PYTHON"]="/home/brainiac/Program/python3.7/bin/python3.7"
# 编译PyCall
julia> Pkg.build("PyCall")

但是编译过程中仍报错:
错误信息

这个方法仍没有解决此问题,报错信息具体为:

┌ Error: Error building `PyCall`: 
│ DEBUG is_windows = False
│ DEBUG is_apple = False
│ DEBUG Candidate: None
│ DEBUG Not found.
│ DEBUG Candidate: /home/brainiac/Program/python3.7/lib/python3.7/config-3.7m-x86_64-linux-gnu/libpython3.7m.a
│ DEBUG Found: /home/brainiac/Program/python3.7/lib/python3.7/config-3.7m-x86_64-linux-gnu/libpython3.7m.a
...
│ DEBUG Not found.
│ dlopen(/home/brainiac/Program/python3.7/lib/python3.7/config-3.7m-x86_64-linux-gnu/libpython3.7m.a) ==> ErrorException("could not load library \"/home/brainiac/Program/python3.7/lib/python3.7/config-3.7m-x86_64-linux-gnu/libpython3.7m.a\"\n/home/brainiac/Program/python3.7/lib/python3.7/config-3.7m-x86_64-linux-gnu/libpython3.7m.a.so: cannot open shared object file: No such file or directory")
│ dlopen(/home/brainiac/Program/python3.7/lib/libpython3.7m.a) ==> ErrorException("could not load library \"/home/brainiac/Program/python3.7/lib/libpython3.7m.a\"\n/home/brainiac/Program/python3.7/lib/libpython3.7m.a.so: cannot open shared object file: No such file or directory")
│ dlopen(libpython3.7m) ==> ErrorException("could not load library \"libpython3.7m\"\nlibpython3.7m.so: cannot open shared object file: No such file or directory")
│ dlopen(libpython3.7m) ==> ErrorException("could not load library \"libpython3.7m\"\nlibpython3.7m.so: cannot open shared object file: No such file or directory")
│ dlopen(libpython3.7) ==> ErrorException("could not load library \"libpython3.7\"\nlibpython3.7.so: cannot open shared object file: No such file or directory")
│ dlopen(libpython3) ==> ErrorException("could not load library \"libpython3\"\nlibpython3.so: cannot open shared object file: No such file or directory")
│ dlopen(libpython) ==> ErrorException("could not load library \"libpython\"\nlibpython.so: cannot open shared object file: No such file or directory")
│ ERROR: LoadError: Couldn't find libpython; check your PYTHON environment variable.
│ 
│ The python executable we tried was /home/brainiac/Program/python3.7/bin/python3.7 (= version 3.7).
│ Re-building with
│     ENV["PYCALL_DEBUG_BUILD"] = "yes"
│ may provide extra information for why it failed.
│ 
│ Stacktrace:
│  [1] error(::String) at ./error.jl:33
│  [2] find_libpython(::String; _dlopen::typeof(Libdl.dlopen)) at /home/brainiac/Program/julia/julia-1.5.3/julia-depot/packages/PyCall/BD546/deps/buildutils.jl:72
│  [3] find_libpython(::String) at /home/brainiac/Program/julia/julia-1.5.3/julia-depot/packages/PyCall/BD546/deps/buildutils.jl:41
│  [4] top-level scope at /home/brainiac/Program/julia/julia-1.5.3/julia-depot/packages/PyCall/BD546/deps/build.jl:87
│  [5] include(::String) at ./client.jl:457
│  [6] top-level scope at none:5
│ in expression starting at /home/brainiac/Program/julia/julia-1.5.3/julia-depot/packages/PyCall/BD546/deps/build.jl:43
└ @ Pkg.Operations /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/Operations.jl:949

解决方法

再次观察了初始的报错信息后,发现需要install the Python package containing the matplotlib module,原因在于虽然安装的python3.7存在matplotlib库,但系统中的python3.6未安装matplotlib,而且在编译过程中系统路径的问题,虽然设置了ENV["PYTHON"]指向了python3.7的安装位置,但仍不兼容,因此为系统预安装的python安装matplotlib

# 重置ENV["PYTHON"]
julia> ENV["PYTHON"]=""
julia> Pkg.build("PyCall")
julia> Pkg.add("Conda")
julia> import Conda
julia> Conda.add("matplotlib")
[ Info: Running `conda install -y matplotlib` in root environment
Collecting package metadata (current_repodata.json): done
Solving environment: done

## Package Plan ##

  environment location: /home/brainiac/Program/julia/julia-1.5.3/julia-depot/conda/3

  added / updated specs:
    - matplotlib
...
# 重启julia
julia> exit()
$ julia
julia> using Pkg
julia> Pkg.add("Pyplot")
julia> using Random,PyPlot
julia> function f()
           Random.seed!(1)
           r = rand(50)
           @show sum(r)
           display(transpose(r))
           print(transpose(r))
           plot(r)
       end
f (generic function with 1 method)
julia> f()

可以看到弹窗绘图窗口,问题得到解决。
问题解决

The end

希望有所帮助,enjoy coding.

posted @ 2021-05-18 12:32  盼小辉丶  阅读(762)  评论(0编辑  收藏  举报