Paquetes en Julia
Ulises M. Alvarez

El problema de las actualizaciones

Actualizar, julia, a última versión disponible plantea algunos problemas, entre ellos podemos mencionar:

  • Incompatibilidad de programas por cambios en la sintaxis del lenguaje.
  • Necesidad de reinstalar los paquetes de nuestra librería.

Administración de la biblioteca de paquetes

Julia, cuenta con varias herramientas para la administración de paquetes. Todas estas herramientas están disponibles en el módulo, Base.Pkg, que se incluye por defecto.

La ayuda para dichas herramientas está disponible en la consola de las sesiones interactivas y en línea:

Estado de los paquetes

El estado de los paquetes se puede obtener con el comando:

Pkg.status()

In [1]:
Pkg.status()  # Obtenemos el "estado" de la biblioteca


1 required packages:
 - IJulia                        1.5.0
8 additional packages:
 - BinDeps                       0.6.0
 - Compat                        0.26.0
 - Conda                         0.5.3
 - JSON                          0.12.0
 - MbedTLS                       0.4.5
 - SHA                           0.3.3
 - URIParser                     0.1.8
 - ZMQ                           0.4.3

Como podemos observar, en este caso tenemos paquetes:

  • requeridos, esto es, instalados por el usuario.
  • adicionales, paquetes que se descargaron como dependencias.

Si no ha instalado ningún paquete al momento de ejecutar el comando, obtendrá:

Pkg.status()
INFO: Initializing package repository ~/.julia/v0.5
INFO: Cloning METADATA from git://github.com/JuliaLang/METADATA.jl
No packages installed.

Directorio de trabajo

Para mostrar el directorio base donde están, o estarán, los paquetes usamos:

Pkg.dir()

Si deseamos saber dónde está instalado un paquete en particular, usamos:

Pkg.dir("IJulia")

Paquetes disponibles para instalar

Para obtener una lista de los paquetes que podríamos instalar desde Internet, usamos:


In [2]:
Pkg.available()        # Qué librerías (paquetes) están disponibles para instalar


Out[2]:
1410-element Array{AbstractString,1}:
 "AbstractDomains"       
 "AbstractFFTs"          
 "AbstractTables"        
 "AbstractTrees"         
 "Accumulo"              
 "ACME"                  
 "ActiveAppearanceModels"
 "Actors"                
 "ActuarialScience"      
 "AdaptiveDistanceFields"
 "AdjacentFloats"        
 "AffineInvariantMCMC"   
 "AffineTransforms"      
 ⋮                       
 "Xtensor"               
 "YAML"                  
 "Yelp"                  
 "Yeppp"                 
 "YT"                    
 "ZChop"                 
 "Zeros"                 
 "ZipCode"               
 "ZipFile"               
 "Zlib"                  
 "ZMQ"                   
 "ZVSimulator"           

Este comando regresa un vector de tipo String:


In [3]:
typeof(Pkg.available())  # Qué tipo de respuesta nos regresa Pkg.available()


Out[3]:
Array{AbstractString,1}

Por lo que podríamos usar las funciones disponibles para cadenas de caracteres, como contains()


In [4]:
contains(==,             # igualdad que evaluará la función
    Pkg.available(),     # vector donde hacemos la búsqueda
    "IJuliaPortrayals")  # cadena a buscar


Out[4]:
true

Paquetes instalados

Para facilitar las consultas, julia, también cuenta con una función que nos permite obtener una lista de los paquetes que ya tenemos instalados:


In [5]:
Pkg.installed()


Out[5]:
Dict{String,VersionNumber} with 9 entries:
  "URIParser" => v"0.1.8"
  "Conda"     => v"0.5.3"
  "JSON"      => v"0.12.0"
  "BinDeps"   => v"0.6.0"
  "Compat"    => v"0.26.0"
  "IJulia"    => v"1.5.0"
  "SHA"       => v"0.3.3"
  "MbedTLS"   => v"0.4.5"
  "ZMQ"       => v"0.4.3"

Como se puede observar, este comando regresa un diccionario:


In [6]:
typeof(Pkg.installed())


Out[6]:
Dict{String,VersionNumber}

Las variables de tipo diccionario cuentan con sus propias funciones, por ejemplo:


In [7]:
haskey(Pkg.installed(), "PlotlyJS")


Out[7]:
false

Actualizando biblioteca de una versión a otra

Para reproducir la biblioteca de la versión anterior de julia, en sistemas tipo Unix (Linux, MacOS, etc.), se puede usar el siguiente procedimiento:

1. Copiar el archivo REQUIERE de la versión anterior a la nueva:

$ ls ~/.julia/                             # obtenemos listado del directorio local de julia
lib  v0.5  v0.6                           

$ cp ~/.julia/v0.5/REQUIRE ~/.julia/v0.6/  # copiamos "REQUIERE" de v0.5 a v0.6
$ cat ~/.julia/v0.6/REQUIRE                # mostramos el contenido de "REQUIERE"
IJulia
PyPlot
Weave
Plots
PlotlyJS
UnicodePlots
StatPlots
PlotRecipes
Blink
Rsvg
Distributions
GLM
RDatasets
DataFrames
DataArrays
LaTeX
Winston
Gadfly
Measures
Compose

2. Ahora, lance la nueva versión de julia y, desde la REPL, ejecute:

Pkg.resolve()

Ejercicio

Se desea hacer una función que:

  • Verifique si un paquete está o no instalado.
  • Si no está instalado, debe descargarlo y cargarlo a la REPL.
  • Si ya está instalado, debe cargarlo a la REPL.

In [8]:
if !haskey(Pkg.installed(), "Distributions")  # ¿Está instalado el paquete?
    Pkg.add("Distributions")                  # Si no está, lo instalamos
    using Distributions
else
    using Distributions
end


INFO: Cloning cache of Calculus from https://github.com/johnmyleswhite/Calculus.jl.git
INFO: Cloning cache of DataStructures from https://github.com/JuliaCollections/DataStructures.jl.git
INFO: Cloning cache of Distributions from https://github.com/JuliaStats/Distributions.jl.git
INFO: Cloning cache of PDMats from https://github.com/JuliaStats/PDMats.jl.git
INFO: Cloning cache of QuadGK from https://github.com/JuliaMath/QuadGK.jl.git
INFO: Cloning cache of Rmath from https://github.com/JuliaStats/Rmath.jl.git
INFO: Cloning cache of SpecialFunctions from https://github.com/JuliaMath/SpecialFunctions.jl.git
INFO: Cloning cache of StatsBase from https://github.com/JuliaStats/StatsBase.jl.git
INFO: Cloning cache of StatsFuns from https://github.com/JuliaStats/StatsFuns.jl.git
INFO: Installing Calculus v0.2.2
INFO: Installing DataStructures v0.5.3
INFO: Installing Distributions v0.13.0
INFO: Installing PDMats v0.7.0
INFO: Installing QuadGK v0.1.2
INFO: Installing Rmath v0.1.6
INFO: Installing SpecialFunctions v0.1.1
INFO: Installing StatsBase v0.16.0
INFO: Installing StatsFuns v0.5.0
INFO: Building Rmath
INFO: Attempting to Create directory /home/uma/.julia/v0.6/Rmath/deps/downloads
INFO: Downloading file https://github.com/JuliaLang/Rmath-julia/archive/v0.1.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   127    0   127    0     0    438      0 --:--:-- --:--:-- --:--:--   437
100  165k  100  165k    0     0  75278      0  0:00:02  0:00:02 --:--:--  369k
INFO: Done downloading file https://github.com/JuliaLang/Rmath-julia/archive/v0.1.tar.gz
INFO: Attempting to Create directory /home/uma/.julia/v0.6/Rmath/deps/src
INFO: Attempting to Create directory /home/uma/.julia/v0.6/Rmath/deps
INFO: Directory /home/uma/.julia/v0.6/Rmath/deps already created
INFO: Attempting to Create directory /home/uma/.julia/v0.6/Rmath/deps/usr/lib
INFO: Changing Directory to /home/uma/.julia/v0.6/Rmath/deps/src/Rmath-julia-0.1
lbeta.c: In function ‘lbeta’:
lbeta.c:72:5: warning: this ‘else’ clause does not guard... [-Wmisleading-indentation]
     else
     ^~~~
lbeta.c:76:2: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘else’
  return log(gammafn(p) * (gammafn(q) / gammafn(p + q)));
  ^~~~~~
randmtzig.c: In function ‘gv_randi’:
randmtzig.c:92:5: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
     return *((uint64_t *) &r) & 0x000fffffffffffff;
     ^~~~~~
randmtzig.c: In function ‘randi’:
randmtzig.c:104:5: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
     return *((uint64_t *) &r) & 0x000fffffffffffff;
     ^~~~~~
INFO: Changing Directory to /home/uma/.julia/v0.6/Rmath/deps/src/Rmath-julia-0.1
INFO: Package database updated
INFO: Precompiling module Distributions.

In [14]:
workspace()

In [15]:
function p_load(a::String)
    if !haskey(Pkg.installed(), a)  # ¿Está instalado el paquete?
        Pkg.add(a)                  # Si no está, lo instalamos
        # using Distributions
    else
        #using Distributions
        println("Ya esta")
    end
end


Out[15]:
p_load (generic function with 1 method)

In [16]:
methods(p_load)


Out[16]:
1 method for generic function p_load:
  • p_load(a::String) at In[15]:2

In [17]:
p_load("IJulia")


Ya esta

In [18]:
p_load(Distributions)


UndefVarError: Distributions not defined

Stacktrace:
 [1] execute_request(::LastMain.LastMain.ZMQ.Socket, ::LastMain.LastMain.IJulia.Msg) at /home/uma/.julia/v0.6/IJulia/src/execute_request.jl:156
 [2] eventloop(::LastMain.LastMain.ZMQ.Socket) at /home/uma/.julia/v0.6/IJulia/src/eventloop.jl:8
 [3] (::LastMain.LastMain.IJulia.##9#12)() at ./task.jl:335

In [11]:
Pkg.status()


2 required packages:
 - Distributions                 0.13.0
 - IJulia                        1.5.0
16 additional packages:
 - BinDeps                       0.6.0
 - Calculus                      0.2.2
 - Compat                        0.26.0
 - Conda                         0.5.3
 - DataStructures                0.5.3
 - JSON                          0.12.0
 - MbedTLS                       0.4.5
 - PDMats                        0.7.0
 - QuadGK                        0.1.2
 - Rmath                         0.1.6
 - SHA                           0.3.3
 - SpecialFunctions              0.1.1
 - StatsBase                     0.16.0
 - StatsFuns                     0.5.0
 - URIParser                     0.1.8
 - ZMQ                           0.4.3

Reproducibilidad


In [12]:
versioninfo()


Julia Version 0.6.0-rc2.0
Commit 68e911be53* (2017-05-18 02:31 UTC)
Platform Info:
  OS: Linux (x86_64-solus-linux)
  CPU: Intel(R) Core(TM) i7-3615QM CPU @ 2.30GHz
  WORD_SIZE: 64
  BLAS: libopenblas (NO_AFFINITY CORE2)
  LAPACK: libopenblas
  LIBM: libopenlibm
  LLVM: libLLVM-4.0.0 (ORCJIT, ivybridge)

In [13]:
Dates.today()


Out[13]:
2017-06-16