I am writing a Lua script and am trying to use require on a file that exists in the same directory as the main script. I cannot seem to get require to work in this case and have tried several solutions I have found but none seem to work. I have the following files together in a directory:
main.lua
helper.lua
I've tried the following solutions and gotten the error following each:
Solution 1:
local folderOfThisFile = (...):match("(.-)[^%.]+$")
local helper = require(folderOfThisFile .. 'helper')
lua: ...domizerWPF\DataFiles\LUA\main.lua:2: attempt to index local 'pathOfThisFile' (a nil value)
stack traceback:
...domizerWPF\DataFiles\LUA\main.lua:2: in main chunk
[C]: ?
Solution 2:
package.path = "/?.lua;" .. package.path
local helper = require('helper')
lua: ...domizerWPF\DataFiles\LUA\main.lua:2: module 'helper' not found:
no field package.preload['helper']
no file '/helper.lua'
no file '.\helper.lua'
no file 'C:\Program Files (x86)\Lua\5.1\lua\helper.lua'
no file 'C:\Program Files (x86)\Lua\5.1\lua\helper\init.lua'
no file 'C:\Program Files (x86)\Lua\5.1\helper.lua'
no file 'C:\Program Files (x86)\Lua\5.1\helper\init.lua'
no file 'C:\Program Files (x86)\Lua\5.1\lua\helper.luac'
no file '.\helper.dll'
no file '.\helper51.dll'
no file 'C:\Program Files (x86)\Lua\5.1\helper.dll'
no file 'C:\Program Files (x86)\Lua\5.1\helper51.dll'
no file 'C:\Program Files (x86)\Lua\5.1\clibs\helper.dll'
no file 'C:\Program Files (x86)\Lua\5.1\clibs\helper51.dll'
no file 'C:\Program Files (x86)\Lua\5.1\loadall.dll'
no file 'C:\Program Files (x86)\Lua\5.1\clibs\loadall.dll'
stack traceback:
[C]: in function 'require'
...domizerWPF\DataFiles\LUA\main.lua:2: in main chunk
[C]: ?
I've tried variations on Solution 2 with various paths such as "?.lua;" and "./?.lua;" to no avail.
These two lines of the error message shed some light on your problem:
no file '/helper.lua'
no file '.\helper.lua'
The first line is due to your change to package.path. As you can see, it looks for a "/helper.lua" file that doesn't exist so its not doing anything. The second line is due to the default package.path and is looking for a "helper.lua" in the current working directory. Since its not finding, your current working directory must not be the directory your main.lua is located on.
The fix is to either make the current working directory the directory where main.lua and helper.lua are located or to add "C:\\path\\to\\your\\lua\\project\\?.lua" to the package.path
i am still learning lua but here is what I can whip up for you,
if you don't have a file system API installed then you can make a string variable with your curent working dir in it and you can add to it like this
local cwd="C:\users\user\Desktop\"
dofile(cwd.."program.lua")
thats what I do, and I have no problems with it
If you mean that you want to be able to invoke the program from any directory and that it correctly locates the required files, then you can use this solution (you only need it within main.lua):
local base_path = string.match(arg[0], '^(.-)[^/\\]*$')
package.path = string.format("%s;%s?.lua", package.path, base_path)
This works by adding the directory where the file is to the package path, so that require can work on the files in that directory. Lua doesn't do this automatically yet (Python does, since version 2.6 or so); hopefully it will be implemented in future. You can also use base_path to refer to other files in the same directory. In my case, for example, there is a SQLite database in that directory and the program needs to open it, so I use this:
local database_filename = base_path .. 'db.sqlite'
You can also make base_path a global so that it's available to other modules if necessary.
Related
I am new to Lua. I compiled a JS file to lua 5.2 using castl:
castl -o script.js
This created a file named script.js.lua. This is the first line of my new lua file:
local _ENV = require("castl.runtime");
I tried running that file with lua52 script.js.lua, but I got this error:
C:\Program Files\lua-5.2.4_Win64_bin\lua52.exe: script.js.lua:1: module 'castl.runtime' not found:
no field package.preload['castl.runtime']
no file 'C:\Program Files\lua-5.2.4_Win64_bin\lua\castl\runtime.lua'
no file 'C:\Program Files\lua-5.2.4_Win64_bin\lua\castl\runtime\init.lua'
no file 'C:\Program Files\lua-5.2.4_Win64_bin\castl\runtime.lua'
no file 'C:\Program Files\lua-5.2.4_Win64_bin\castl\runtime\init.lua'
no file '.\castl\runtime.lua'
no file 'C:\Program Files\lua-5.2.4_Win64_bin\castl\runtime.dll'
no file 'C:\Program Files\lua-5.2.4_Win64_bin\loadall.dll'
no file '.\castl\runtime.dll'
no file 'C:\Program Files\lua-5.2.4_Win64_bin\castl\runtime52.dll'
no file '.\castl\runtime52.dll'
no file 'C:\Program Files\lua-5.2.4_Win64_bin\castl.dll'
no file 'C:\Program Files\lua-5.2.4_Win64_bin\loadall.dll'
no file '.\castl.dll'
no file 'C:\Program Files\lua-5.2.4_Win64_bin\castl52.dll'
no file '.\castl52.dll'
stack traceback:
[C]: in function 'require'
script.js.lua:1: in main chunk
[C]: in ?
What am I missing? I am on Windows 10.
To answer your question
What am I missing?
Your problem is that you use a function require, but you don't know what this function does. Therefore, you cannot understand the errors it throws when it fails to do what you're expecting it to do.
So first refer to the Lua manual:
https://www.lua.org/manual/5.3/manual.html#pdf-require
There you'll find:
require searches for a Lua loader using the path stored in
package.path. If that also fails, it searches for a C loader using the
path stored in package.cpath. If that also fails, it tries an
all-in-one loader (see package.searchers).
and https://www.lua.org/manual/5.3/manual.html#pdf-package.path
The path used by require to search for a Lua loader.
At start-up, Lua initializes this variable with the value of the
environment variable LUA_PATH_5_3 or the environment variable LUA_PATH
or with a default path defined in luaconf.h, if those environment
variables are not defined. Any ;; in the value of the environment
variable is replaced by the default path.
For additional reading:
https://www.lua.org/pil/8.1.html
Entering "Lua require" into any web search will also result in plenty of solutions to your problem.
As hjpotter92 already stated in his comment, you have to tell your computer where to look for the files you want to require unless they are already located in the default folders.
Add the file's location to your LUA_PATH environment variable or add it to the package.path string before calling the respective require.
I'll leave an answer here since I believe that answer provided is actually not helping to someone who does not know anything about Lua ecosystem.
In order to require("castl.runtime") to be resolved one need to set LUA_PATH, in this case, for the sake of simplicity let's assume that castl distrib is located at /Users/me/castl, then you can:
export LUA_PATH="/Users/me/castl/lua/?.lua"
Now if you'll run Lua script it will be executed properly.
I'm struggling with pyinstaller. Whenever I build this specific script with a kivy GUI and a .kv file, and run the .exe after the build, I get a fatal error:
IOError: [Errno 2] No such file or directory: 'main.kv'
I've tried adding the .kv file, as well as a mdb and dsn file (for pypyodbc) using --add-data, but I get an error: unrecognized arguments: --add-data'main.kv'. (There were more --add-data arguments for the other files mentioned.)
Are there any solutions for this or maybe alternative methods?
As others (#Anson Chan, #schlimmchen) have said:
If you want to add some extra files, you should use Adding Data Files.
Two ways to implement
Command Line: add parameter to --add-data
Spec file: add parameter to datas=
Generated when running pyinstaller the first time.
Then later you can edit your *.spec file.
Then running pyinstaller will directly use your *.spec file.
Parameter Logic
Parameter in --add-data or datas=:
--add-data:
format: {source}{os_separator}{destination}
os_separator:
Windows: ;
Mac/Linux/Unix: :
source and destination
Logic:
source: path to single or multiple files, supporting glob syntax. Tells PyInstaller where to find the file(s).
destination
file or files: destination folder which will contain your source files at run time.
* NOTE: NOT the destination file name.
folder: destination folder path, which is RELATIVE to the destination root, NOT an absolute path.
Examples:
Single file: 'src/README.txt:.'
multiple files: '/mygame/sfx/*.mp3:sfx'
folder: '/mygame/data:data'
datas=
Format: list or tuple.
Examples: see the following.
added_files = [
( 'src/README.txt', '.' ),
( '/mygame/data', 'data' ),
( '/mygame/sfx/*.mp3', 'sfx' )
]
a = Analysis(...
datas = added_files,
...
)
Your case
For your (Windows OS) here is:
--add-data in command line
pyinstaller -F --add-data "main.kv;." yourtarget.py
OR:
datas= in yourtarget.spec file, see following:
a = Analysis(...
datas = ["main.kv", "."],
...
)
If you check pyinstaller -h for help, you can find --add-data option works like this [--add-data <SRC;DEST or SRC:DEST>]. So in your case try
pyinstaller -F --add-data "main.kv;main.kv" yourtarget.py
The solution is to run: pyi-makespec yourscript.py
Then edit the yourscript.spec script and add the files under datas in a= Analysis.
datas=[ ( '/pathToYourFile/main.kv', '.' )]
then run pyinstaller yourscript.spec
should be good after that.
Next -F or --onefile option is assumed when running pyinstaller.
Note that (MacOS Monterey, 12.2 here) the expected folder hierarchy w/in you .app file will be similar to this,
pyinstaller does not add files nor create necessary folders into any of the folders of this folder structure; at least not in any apparent way. You won't find them.
However, when the application runs, a temporary folder is used under /var/folders which is very different from the folder structure in point 1. above. print(os.path.dirname(__file__)) while running the application will reveal which exact temporary folder is used each time it runs. For convenience, let's call it my_app_tmp_folder i.e. your app runs under the folder /var/folder/my_app_tmp_folder
Then, pyinstaller adds data files or creates necessary directories w/in this temporary folder. In other words, when the application runs, all added files will be there and according to the specified folder structure (through --add-data option). print(os.listdir(os.path.dirname(__file__))) will show system and application needed files and folders.
Bottom line: Files specified w/ --add-data option will be visible w/in /var/folder/my_app_tmp_folder when running and not w/in the *.app folder.
Some useful links from documentation:
https://pyinstaller.readthedocs.io/en/stable/runtime-information.html#using-file
https://pyinstaller.readthedocs.io/en/stable/spec-files.html#adding-files-to-the-bundle
https://pyinstaller.readthedocs.io/en/stable/operating-mode.html#bundling-to-one-file
My application had this issue and a subsequent issue that is likely, if not inevitable.
1. --add-data for a kv file
Use --add-data as in the answer by crifan.
2. Kivy still can't find the file
Once PyInstaller has the kv file in the correct directory, Kivy still can't find the file.
Possible Symptoms:
GUI launches, but screen is black and empty.
An AttributeError error that depends on the application code.
AttributeError Examples:
This question
My own case:
AttributeError: 'NoneType' object has no attribute 'ids'
Fortunately, this answer solves the problem.
I have a simple script that I want to import into another with require, but when I run it from Notepad++ I get the usual error that require produces.
The funny thing is that it worked an hour ago and I did not restart the computer since then.
The files are in the same directory, so the simple file name (without .lua) worked and should still work. (relative path)
Lua runs the script just fine.
this is what I entered in Notepad:
cmd /k lua "$(FULL_CURRENT_PATH)"
Earlier I also had a problem with Penlight, maybe there is some connection, so here it is:
I tried to require"pl" but it failed to find the module. (ran from SciTE, worked prevously)
I tried it in the Lua command line and it worked like a charm.
Tried again in SciTE and voila it worked again.
I have no idea what causes any of them.
ps.: using the lfs module and os.execute("cd /d ...path...") did not work
Lua is searching for your required module in the folders of LUA_PATH. In the script you run via F5, put this statement:
print('current path is:')
os.execute('cd')
require 'someModuleThatDoesntExist'
After printing the "working" forlder (Program Files/Notepad++), it tries to find the required module and fails. The traceback shows that Lua looks through many different folders, none of them being the one containing FULL_CURRENT_PATH, so it can't find the module.
You have several choices:
put your scripts in one of the listed paths
set LUA_PATH in your environment to contain the folder name where your scripts are located
change package.path from your script so it knows where to look for other modules. You could do this by either:
including an extra parameter to your F5, namely CURRENT_DIRECTORY, and make your script take its first command line param (CURRENT_DIRECTORY) to add it to package.path
parse arg[0] when your script starts, to get the folder containing script, and extend package.path
For example with #3, first option, you would use
cmd /k lua "$(FULL_CURRENT_PATH)" "$(CURRENT_DIRECTORY)"
in notepad++ and in your Lua module you would use
thisModuleDir = arg[1]
package.path = thisModuleDir .. ";" .. package.path
require 'yourmodule'
I am using Lua for Windows.
I am trying a sample script from the wxLua website; however, when I run the script, it fails on the first line, which is require 'wx' with:
lua: cannot open wx: No such file or directory
However, when executing require 'wx' in the REPL/interpreter, it works OK.
I have done another script to output print(package.cpath) and print(package.path), and they seem the same to me as in the REPL.
Why, when running the script, is it not able to find 'wx'?
In this instance, I am running both the script and the shell/REPL from the same folder.
The value of package.cpath (produced by test script and Lua shell):
.\?.dll;.\?51.dll;C:\Program Files (x86)\Lua\5.1\?.dll;C:\Program Files (x86)\Lu a\5.1\?51.dll;C:\Program Files (x86)\Lua\5.1\clibs\?.dll;C:\Program Files (x86)\ Lua\5.1\clibs\?51.dll;C:\Program Files (x86)\Lua\5.1\loadall.dll;C:\Program File s (x86)\Lua\5.1\clibs\loadall.dll
and package.path (again, the same from the script and Lua shell):
;.\?.lua;C:\Program Files (x86)\Lua\5.1\lua\?.lua;C:\Program Files (x86)\Lua\5.1\lua\?\init.lua;C:\Program Files (x86)\Lua\5.1\?.lua;C:\Program Files (x86)\Lua\5.1\?\init.lua;C:\Program Files (x86)\Lua\5.1\lua\?.luac
There is a wx.dll in C:\Program Files (x86)\Lua\5.1\clibs which is referenced by the cpath value above.
OK, this was my own stupidity: I named the file wx.lua, so obviously require was trying to pick up the script itself.
By simply renaming the file, it works fine.
I downloaded LuaEdit to use as an IDE and debug tool however I'm having trouble using it for even the simplest things. I've created a solution with 2 files in it, all of which are stored in the same folder. My files are as follows:
--startup.lua
require("foo")
test("Testing", "testing", "one, two, three")
--foo.lua
foo = {}
print("In foo.lua")
function test(a,b,c) print(a,b,c) end
This works fine when in my C++ compiler when accessed through some embed code, however when I attempt to use the same code in LuaEdit, it crashes on line 3 require("foo") with an error stating:
module 'foo' not found:
no field package.preload['foo']
no file 'C:\Program Files (x86)\LuaEdit 2010\lua\foo.lua'
no file 'C:\Program Files (x86)\LuaEdit 2010\lua\foo\init.lua'
no file 'C:\Program Files (x86)\LuaEdit 2010\foo.lua'
no file 'C:\Program Files (x86)\LuaEdit 2010\foo\init.lua'
no file '.\foo.lua'
no file 'C:\Program Files (x86)\LuaEdit 2010\foo.dll'
no file 'C:\Program Files (x86)\LuaEdit 2010\loadall.dll'
no file '.\battle.dll'
I have also tried creating these files prior to adding them to a solution and still get the same error. Is there some setting I'm missing? It would be great to have an IDE/debugger but it's useless to me if it can't run linked functions.
The issue is probably that your Lua files are not on the path in package.path (for C files this is package.cpath).
My guess is that the LuaEdit program is not launched in the directory you have your files in, and hence does not have a match for eg .\foo.lua.
You have 3 simple solutions to this (from dumb to smarter):
Find out what path LuaEdit considers as ./ and put your files there.
Open up a terminal in the right directory (the one containing your files), and run LuaEdit from there.
Add the path the files are on to package.path and package.cpath before doing any require's
You may need to put:
lua
package.path = package.path..";c:/path/to/my/files/?.lua"
at the beginning of your files before any require (as jpjacobs indicated). I couldn't find any way to provide this from LuaEdit itself. It appears it runs the script using its full path, but keeps its current dir set to whatever it was when the IDE was started. If you run LuaEdit using full path from your application folder, it should work fine even without package.path changes.
While the IDE itself works fine with its own modules/libraries, it doesn't mean it makes them available to the application it runs.
(shameless plug) If you're still not happy with LuaEdit, I'd offer ZeroBrane Studio Lua IDE as an alternative, It's based on the same wxLua framework, but provides a bit more functionality and doesn't have this particular issue you're facing. It also supports remote debugging, so you should be able to debug your Lua scripts directly from your application.