logo

줄리아에서 설치된 패키지 목록 가져오는 법 📂줄리아

줄리아에서 설치된 패키지 목록 가져오는 법

개요

줄리아 재설치를 많이하는 스타일일수록 패키지를 새로 설치해야하고 까다로울 일이 많다. 그래서 설치된 패키지 목록을 보고 그 중 빈 패키지를 자동으로 설치해주는 헤더를 만들면 편리한데, 문제는 그 패키지 목록을 얻는게 녹록치 않다는 것이다.

코드

Pkg.installed()

using Pkg
Pkg.installed()
keys(Pkg.installed())
julia> Pkg.installed()
┌ Warning: Pkg.installed() is deprecated
└ @ Pkg ...\Pkg.jl:829
Dict{String, VersionNumber} with 26 entries:
  "CSV"                        => v"0.10.15"
  "PlotlyKaleido"              => v"2.3.0"
  "Random"                     => v"1.11.0"
  ⋮                            => ⋮

가장 깔끔하게 지금 설치된 패키지 목록을 이름과 버전의 딕셔너리 형태로 리턴하지만, 경고문에서 알 수 있듯 곧 없어질 함수다. 그냥 keys로 딕셔너리의 키만 가져오면 되므로 이제부터 설명할 방법들에 비해서 압도적으로 편리하다. 혼자 사용하는 프로그램에서는 그냥 실컷 쓰고, 나중에 정말 버려지면 다른 대안으로 갈아타는 게 좋을 것이다.

Pkg.dependencies()

Pkg.dependencies()
getproperty.(collect(values(Pkg.dependencies())), :name)
julia> Pkg.dependencies()
Dict{Base.UUID, Pkg.API.PackageInfo} with 315 entries:
  UUID("a4ae2306-e953-59d6-aa16-d00cac43593b") => PackageInfo("libaom_jll", v"3.12.1+0", "4bba74fa59ab0755…
  UUID("0c81fc1b-5583-44fc-8770-48be1e1cca08") => PackageInfo("InputBuffers", v"1.1.1", "e5392ea00942566b6…
  UUID("7c1d4256-1411-5781-91ec-d7bc3513ac07") => PackageInfo("DynamicPolynomials", v"0.6.3", "ca693f8707a…
  UUID("53ae85a6-f571-4167-b2af-e1d143709226") => PackageInfo("SciMLStructures", v"1.7.0", "566c4ed301ccb2…
  ⋮                                            => ⋮

패키지의 종속성을 전부 파악할 수 있는 패키지 정보의 딕셔너리를 리턴한다. values로 밸류를 가져온다음 getproperty:name 속성만 가져오면 패키지 이름의 배열을 얻을 수 있다. 문제는 이 패키지 목록이 종속성을 모두 파악한 것이 무색하게 진짜 사용자가 설치한 패키지의 목록을 가져오는 게 아니라 줄리아 환경에서 Mainfest.toml를 참조하다보니 실제와 맞지 않는다는 것이다.

Pkg.status()

Pkg.status()
buf = IOBuffer()
Pkg.status(; io=buf)
output = String(take!(buf))
_output = strip.(getproperty.(collect(eachmatch(r"] .+ v", output)), :match), Ref([' ', ']', 'v']))
julia> Pkg.status()
Status `C:\Users\rmsms\.julia\environments\v1.12\Project.toml`
  [336ed68f] CSV v0.10.15
  [861a8166] Combinatorics v1.0.3
  [a93c6f00] DataFrames v1.8.0
  [7806a523] DecisionTree v0.12.4
  [b4f34e82] Distances v0.10.12
⌃ [7a1cc6ca] FFTW v1.9.0
  [38e38edf] GLM v1.9.0
  [86223c79] Graphs v1.13.1
  [033835bb] JLD2 v0.6.2
  [b964fa9f] LaTeXStrings v1.4.0
  [470638dc] NoiseRobustDifferentiation v0.2.4
  [e9f21f70] OpenAI v0.12.0
  [9b87118b] PackageCompiler v2.2.2
  [a03496cd] PlotlyBase v0.8.21
  [f2990250] PlotlyKaleido v2.3.0
⌃ [91a5bcdd] Plots v1.40.19
⌃ [08abe8d2] PrettyTables v3.0.8
  [92933f4c] ProgressMeter v1.11.0
  [2913bbd2] StatsBase v0.34.6
  [69024149] StringEncodings v0.3.7
⌃ [0c5d862f] Symbolics v6.54.0
  [fdbf4ff8] XLSX v0.10.4
  [ade2ca70] Dates v1.11.0
  [37e2e46d] LinearAlgebra v1.12.0
  [9a3f8284] Random v1.11.0
  [2f01184e] SparseArrays v1.12.0
Info Packages marked with ⌃ have new versions available and may be upgradable.

마지막 방법으로 찾은 것이 REPL에서 Pkg.status()을 통해 출력되는 패키지의 목록을 문자열로 탈취하는 것이다. IOBuffer를 통해 Pkg.status()의 출력을 버퍼에 담고, take!로 문자열로 바꾼다음, 정규표현식 r"] .+ v"로 패키지 이름과 버전이 있는 줄을 모두 얻는다. 그 후 getproperty:match 속성만 가져오고, strip으로 앞뒤의 공백과 ], v 문자를 제거하면 깔끔하게 패키지 이름의 배열을 얻을 수 있다.

다소 복잡하지만 원리를 알고 한 줄 한 줄 파보면 그렇게 어려운 기교는 아니고, 적어도 포스트를 작성하는 현재 시점에서는 가장 부작용이 적고 깔끔한 방법이다.

다음은 이 과정을 그냥 쉽게 쓸 수 있게끔 installed라는 함수로 작성한 것이다.

function installed()
    Pkg.status()
    buf = IOBuffer()
    Pkg.status(; io=buf)
    output = String(take!(buf))
    return strip.(getproperty.(collect(eachmatch(r"] .+ v", output)), :match), Ref([' ', ']', 'v']))
end

환경

  • OS: Windows
  • julia: v1.20.0