Загружать модули Julia по требованию

#matplotlib #julia

#matplotlib #julia

Вопрос:

У Меня у меня очень простой вопрос. Возможно ли загружать модули по требованию в Julia. То есть, могут ли модули загружаться тогда, когда они действительно необходимы, вместо того, чтобы загружаться во время «синтаксического анализа» на верхнем уровне.

Сценарий использования, который я имею в виду, заключается в том, что у меня есть некоторый набор кода, который способен выполнять некоторые построения с помощью PyPlot, но код далеко не всегда выполняется.

На данный момент это означает, что у меня на верхнем уровне есть оператор типа using PyPlot , загрузка которого занимает довольно много времени.

(Да, я знаю: не следует часто перезапускать Julia, бла-бла-бла … но, тем не менее, это вызывает раздражение)

Есть ли способ гарантировать, что PyPlot загружается только в том случае, если это действительно необходимо? Самой простой идеей было бы включить using PyPlot внутри функции, которая фактически выполняет построение графика

 function my_plot()
    using PyPlot
    plot(1:10,1:10)
end
  

но это приводит к синтаксической ошибке:

 ERROR: syntax: "using" expression not at top level
  

Итак, есть ли другой способ добиться этого?

Комментарии:

1. вы могли бы eval это using выразить в глобальной области.

2. @Gnimuc Спасибо за ваш комментарий, но я не понимаю, что вы имеете в виду. Не могли бы вы привести пример?

3. добавить @eval перед using PyPlot

Ответ №1:

Инструкция «using» выполняется при обнаружении строки кода и не обязательно должна находиться в верхней части файла. Это должно быть в глобальной области видимости, что означает, что переменные в модуле, загруженные с помощью «using», будут доступны для всех функций в вашей программе после выполнения инструкции «using», а не только для одной функции, как это может произойти в локальной области видимости функции.

Если вы вызываете инструкцию using как выражение в инструкции Julia eval, весь код, выполняемый в инструкции «eval» в Julia, автоматически выполняется в глобальной области видимости, даже если синтаксический вызов eval выполняется в локальной области видимости функции. Итак, если вы используете макрос @eval

 function my_plot()
    @eval using PyPlot  # or without the macro, as eval(:(using PyPlot))
    plot(1:10,1:10)
end
  

это действует так, как будто использование PyPlot выполняется вне функции, и поэтому позволяет избежать синтаксической ошибки.

Комментарии:

1. Спасибо за ответ. Однако теперь возникают новые проблемы. Когда я помещаю @eval в функцию, она все равно не может найти PyPlot: у меня есть: @eval using PyPlot ; clf() и получаю «ОШИБКА: LoadError: MethodError: нет метода, соответствующего clf() Применимый метод может быть слишком новым: выполняется в мире 25167, в то время как текущий мир 25173. » В каком-то другом месте кода, который я случайно запустил using PyCall , поэтому я все еще получаю столкновение?

2. clf() — это функция PyPlot. Сообщение об ошибке означает, что код, который ссылается на подпрограммы PyPlot, был скомпилирован до запуска с использованием PyPlot. Вы могли бы найти функцию, генерирующую ошибку, и запустить инструкцию using до того, как обнаружится этот код, но поскольку это может оказаться неустойчивым к дальнейшему рефакторингу вашего кода, получение этой ошибки означает, что вы должны просто запустить PyPlot вверху.,

3. Я должен добавить, что иногда указание clf в качестве PyCall, clf() в коде, в котором выполняется вызов clf(), также может работать, поскольку PyPlot() может изменять ссылку clf() с PyCall.clf на PyPlot.clf() при запуске программы.