0Pricing
Lua Academy · Урок

package.path и package.cpath

Настраивайте пути поиска для модулей Lua и C.

«package.path и package.cpath» — бесплатный урок Lua Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Lua Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Lua Academy содержит 4 уроков всего.

Содержимое package.path

package.path — это строка с шаблонами поиска, разделёнными точками с запятой. Каждый шаблон содержит заполнитель ?, который заменяется именем модуля (точки преобразуются в разделители каталогов). Lua проверяет шаблоны по порядку, пока не найдёт файл.

print(package.path)
-- ./?.lua;./?.luac;/usr/local/share/lua/5.4/?.lua;...

-- Dots in module names become directory separators
-- require("foo.bar") -> searches for foo/bar.lua
print(("foo.bar"):gsub("%.", "/"))  -- foo/bar

Добавление путей поиска

Добавляйте пути в начало package.path, чтобы указать каталоги с высоким приоритетом при поиске. Добавление в конец задаёт расположения с более низким приоритетом. Установите эти пути до вызовов require, которым они необходимы.

-- Add multiple directories
package.path = table.concat({
  "./?.lua",
  "./lib/?.lua",
  "./lib/?/init.lua",
  package.path,  -- keep existing paths
}, ";")

-- Now require("json") searches:
-- ./json.lua -> ./lib/json.lua -> ./lib/json/init.lua -> ...

package.cpath для расширений C

package.cpath — это путь поиска модулей-расширений C (динамических библиотек: .so в Linux, .dll в Windows, .dylib в macOS). Соглашение об именовании соответствует соглашениям операционной системы для динамических библиотек.

print(package.cpath)
-- ./?.so;/usr/local/lib/lua/5.4/?.so;...

-- Add a local C library directory
package.cpath = "./clib/?.so;" .. package.cpath

-- require("myextension") will now search:
-- ./clib/myextension.so

Переменная окружения LUA_PATH

Переменная окружения LUA_PATH задаёт начальное значение package.path. Последовательность ;; в LUA_PATH заменяется путём по умолчанию. Используйте это для настройки путей поиска без изменения скриптов — это удобно при развёртывании.

-- Set before launching Lua:
-- export LUA_PATH="./?.lua;./lib/?.lua;;"
-- The ";;" expands to the built-in default path

-- In Lua, check what was set:
print(package.path)

-- You can also use LUA_CPATH for C paths:
-- export LUA_CPATH="./clib/?.so;;"

package.searchpath

package.searchpath(name, path) ищет файл, соответствующий имени, в строке пути. Функция возвращает первое найденное совпадение либо nil и сообщение об ошибке со списком всех проверенных расположений. Это удобно для поиска файлов без их фактической загрузки.

local file, err = package.searchpath("json", package.path)
if file then
  print("Found:", file)
else
  print("Not found. Tried:\n" .. err)
end

-- Useful for checking if a module exists:
local function moduleExists(name)
  return package.searchpath(name, package.path) ~= nil
end
print(moduleExists("json"))

Алгоритм поиска require

При вызове require("mod") Lua выполняет следующие шаги: (1) проверяет package.loaded, (2) проверяет package.preload, (3) ищет файл .lua в package.path, (4) ищет библиотеку C в package.cpath. Побеждает первое найденное совпадение.

-- Simulate what require does:
local function myRequire(name)
  -- 1. Check cache
  if package.loaded[name] ~= nil then
    return package.loaded[name]
  end
  -- 2. Check preload
  if package.preload[name] then
    return package.preload[name]()
  end
  -- 3. Search path
  local file = package.searchpath(name, package.path)
  if file then
    return dofile(file)  -- simplified
  end
  error("module not found: " .. name)
end

Функции загрузки

package.searchers (ранее package.loaders) — это массив функций, которые пытаются найти и загрузить модуль. В эту таблицу можно добавлять собственные функции поиска. Каждая такая функция получает имя модуля и возвращает функцию загрузки или nil.

-- Add a custom searcher that loads from a table
local builtins = {
  myconfig = function()
    return {host="localhost", port=8080}
  end
}

table.insert(package.searchers, 1, function(name)
  local loader = builtins[name]
  if loader then return loader end
end)

local cfg = require("myconfig")
print(cfg.host, cfg.port)   -- localhost  8080

Соглашения об именах модулей

Имена модулей имеют иерархическую структуру и используют точки: "mylib.utils". Обычно пространством имён верхнего уровня служит имя проекта или организации, чтобы избежать конфликтов. Стандартом является нижний регистр. Не используйте дефисы в именах модулей (вместо них используйте символы подчёркивания), поскольку дефисы конфликтуют с синтаксисом Lua.

-- Good: hierarchical, lowercase
-- require("myapp.db.connection")
-- require("myapp.utils.string")

-- Bad: dashes cause syntax issues in dot notation
-- local my-module = require("my-module")  -- SYNTAX ERROR
local mymodule = require("my_module")  -- ok

Отладка путей

Если require не может найти модуль, сообщение об ошибке содержит все проверенные пути. Выведите package.path, чтобы увидеть порядок поиска. Используйте package.searchpath, чтобы интерактивно проверить пути конкретного модуля.

-- Debug require failures:
local ok, err = pcall(require, "missing_module")
if not ok then
  -- The error message shows all tried paths
  print("require failed:")
  print(err)
  print("\nCurrent package.path:")
  for path in package.path:gmatch("[^;]+") do
    print("  " .. path)
  end
end

Сброс пути на значение по умолчанию

Если нужен чистый минимальный путь без системных значений по умолчанию, можно полностью сбросить package.path. Это полезно во встроенных средах Lua, где файловая система ограничена или изолирована.

-- Minimal path for embedded environment
package.path  = "./?.lua;./lib/?.lua"
package.cpath = "./?.so"

-- Or get just the current directory patterns:
local function justLocal()
  return "./?.lua;./?/init.lua"
end

print("Minimal path:", justLocal())

Быстрая проверка

Что обозначает ? в шаблоне package.path?

Повторение: package.path

Краткое содержание:

  • package.path: шаблоны поиска файлов Lua; ? = имя модуля
  • package.cpath: шаблоны поиска библиотек C
  • Добавляйте пути в начало, чтобы задать каталогам высокий приоритет
  • Переменные окружения LUA_PATH/LUA_CPATH задают начальные пути
  • package.searchpath: проверка доступности модуля для поиска
  • Добавляйте собственные функции поиска через package.searchers

Часто задаваемые вопросы

Урок «package.path и package.cpath» бесплатный?

Да — полный текст урока «package.path и package.cpath» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Lua Academy, подпишись на CoddyKit PRO. Курс Lua Academy содержит 4 уроков всего.

Чему я научусь в уроке «package.path и package.cpath»?

Настраивайте пути поиска для модулей Lua и C. Ты практикуешь Lua Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Lua Academy?

Предыдущий опыт не требуется. Lua Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «package.path и package.cpath»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Lua Academy?

Да. Каждый урок Lua Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Функция require
  2. Создание файла модуля
  3. package.path и package.cpath
  4. Шаблоны модулей и рекомендации
← Назад к Lua Academy