0Pricing
Lua Academy · 课时

package.path 和 package.cpath

配置 Lua 模块和 C 模块的搜索路径。

package.path 和 package.cpath 是 CoddyKit 上的免费 Lua Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 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 -> ...

用于 C 扩展的 package.cpath

package.cpath 是 C 扩展模块的搜索路径(共享库:Linux 上为 .so,Windows 上为 .dll,macOS 上为 .dylib)。其命名约定与系统共享库的约定一致。

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) 在 package.path 中搜索 .lua 文件;(4) 在 package.cpath 中搜索 C 库。第一个匹配项会被采用。

-- 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」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Lua Academy 课程的其余内容,请升级到 CoddyKit PRO。 Lua Academy 课程共包含 4 节课。

「package.path 和 package.cpath」这节课中我会学到什么?

配置 Lua 模块和 C 模块的搜索路径。 你通过在浏览器中直接运行的动手代码来练习 Lua Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Lua Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Lua Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 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