In the course of human events, you may need to do something that the hampered lua environment we are provided with simply cannot do. Hence this module.
gm_python provides you with unrestricted access to a python programming environment. It’s my first module so it’s not going to be perfect, but hey, I tried.
It uses Python 2.6. I’m not sure what version it would use if you had python installed on your computer; whether it would use 2.6 which is the one included, or the one installed, I don’t know.
You don’t need python installed on your system to use it.
The functions are stored in the global table py, so you can just do PrintTable(py) to see a list of the commands if you forget them.
Read the readme.
To install, put gm_python.dll in your garrysmod/garrysmod/lua/includes/modules directory, put python26.dll in your garrysmod directory (not garrysmod/garrysmod, just garrysmod), and put python26.zip in your garrysmod directory (not garrysmod/garrysmod, just garrysmod).
DO NOT UNZIP THE ZIP FOLDER unless you just want to look inside it. If you unzip the files and place them in your garrysmod folder, it wont work.
You need the actual .zip file in your garrysmod folder.
If you want to add a module so you can import it from python, just put it in the Lib folder in the python26.zip folder.
All examples assume require(‘python’) and py.Initialize()
This would write the file ‘fefe.bat’ that would echo “ohai from python”, in one folder up from the garrysmod/ folder (two folders up from garrysmod/garrysmod).
def writeFile(name, contents):
file = open(name, ‘w’)
writeFile(’…/ohai.bat’, ‘@ECHO OFF
ECHO ohai from python
Writing files with any extension, as demonstrated here, as well as writing binary files, is possible.
Say we have a file named asdf.py in the garrysmod/garrysmod folder that contains:
import socket def sendApacket(number, contents, ip, port): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto(contents, (ip, port)) numpackets = 1 cont = 'fefe' ip = '192.168.1.101' port = 27005 sendApacket(numpackets, cont, ip, port) print str(numpackets) + ' packet(s) containing "' + cont + '" sent to ' + ip + ':' + str(port)
We run it with:
and printed in our console is: “1 UDP packet(s) containing “fefe” sent to 192.168.1.101:27005”.
And that’s just a very small sample of what you can do with python.
py.Initialize() No arguments. Initializes the Python environment. Do this once and you're set. Returns true if it had to initialize python, false if it did't and Python was already running. If you run it more than once, nothing happens. It just returns false after the first time. py.Terminate() No arguments. Shuts down the Python environment. py.IsInitialized() No arguments. Returns true if Python is initialized, false if otherwise. py.RunString() 1 argument, code to be run in a string. Returns true if Python could parse and run your code, false if Python couldn't. Errors will be printed in the console. This is the main function you should use for coding in the Python environment from lua. Use this function only for stuff that doesn't need to return any values. Remember that python uses space to determine code groups, so include and in your code string when necessary. So for this function, this code is valid: py.RunString("def asdf(): print 'lol'") but this is not: py.RunString("def asdf(): print 'lol'") If you are doing Python from a lua file, just put your entire code string in [[ and ]], and write it like normal Python, and it will keep the newlines and indents when it is run. py.RunConString() 1 argument, code to be run in a string. Returns true if Python could parse and run your code, false if Python couldn't. Errors will be printed in the console. This function is most practical for running Python code from the console. You do not need to use white space, but you should only do one statement at a time or define very simple functions with this. These are all valid statements with this function from within lua: py.RunConString("def asdf(s): print s") py.RunConString("fefe = 1") py.RunConString("file = open('lol.txt', 'b')") py.RunReturnString() 1 argment, code to be run in a string. Returns the result of the code being parsed and run. Errors will appear in the console. You should ONLY use this function when you have to, since it is prone to errors. It returns the result of the evaluation of the python code you pass it (but it still runs it in the environment like normal). So this: py.RunReturnString("2 * 8") would return the number 16. Use this to evaluate only one expression at a time. You may get away with more, but you never know. Again, don't use this unless you have to, and definitely on code that doesn't need to return some value to lua. Regretably, because Python is so much more flexible and has more awesome types than C, only these return types are supported: integers, longs, floating point numbers, and strings. Support is soon to be added for dictionaries, lists, and tuples, which will probably be return as tables. Currently, if the type is one that is not in the list above, it returns the type of the result as a string. So this: py.RunReturnString("[3, 6, 9]") would return the string "List". Strings available for returning are: "Unicode", "Object instance", "Function", "Method", "Module", "Iterator", "Slice", "Generator", "Tuple", "List". A value other than the supported return types or the strings would return "Unsupported return type. This isn't bad." py.RunFile() 1 argument, file path as a string. Returns true if the file was run successfully, false if it failed. use one or multiple ../ in the path argument to go up (a) director(y/ies). The file path starts in the garrysmod directory (not garrysmod/garrysmod, just garrysmod).
py.Send(int number, string or number value) Sets the lua value py.PVals[number] to value. Value may be either a string or number, else it will just be set to a string indicating the type of object you tried to set it to. py.Set(string variable, string or number newvalue) Sets the lua global variable to newvalue. Takes either numbers or strings, or it will be set to a string indicating the type of object you tried to send. py.Run(string lua code to run) Runs an arbitrary piece of lua code. Exactly like doing RunString() from lua.
As it says in RunFile’s description, all file paths begin in the garrysmod (not garrysmod/garrysmod) directory.
It’s not smart to have this on your client when you join servers, as they can SendLua you into doing stuff. I didn’t block it client side because that is a retarded way to do things.
Huge thanks go to Chrisaster for his longsuffering help in starting coding modules. Seriously, it was like
[lua]while 1 do Chris4ster.Ask(StupidQuestion) end[/lua]
(The word Chrisaster with a period after it is blocked.)
If you guys can think of more functions, if I can I will add them.
[li]Changed the name of RunSimpleString to RunString to better reflect it’s usage, and also fixed it to return true on success, not just false on failure.[/li][li]Removed RunReturnString and added the python function gmod.Send() for sending values to lua from python.[/li][li]Added back RunReturnString because in some cases it can provide functionality that gmod.Send() would be less good for doing.[/li][li]Added python function gmod.Set() and gmod.Run()[/li][li]Updated python26.dll and python26.zip to python 2.6.4 from 2.6.2.[/li][/ul]
You can download the source here.