[highlight][b]gm_python[/b][/highlight]
v 1.5b
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 [b]the actual .zip file[/b] 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.
[b]Download:[/b]
[url=http://solidfiles.com/d/88ch][img]http://solidfiles.com/info_imgs/88ch.jpg[/img][/url]
[b]Examples:[/b]
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).
[lua]
py.RunString([[
def writeFile(name, contents):
file = open(name, 'w')
file.write(contents)
file.close()]])
py.RunString([[
writeFile('../ohai.bat', '@ECHO OFF\nECHO.\nECHO ohai from python\nECHO.\nPAUSE\nCLS\nEXIT')]])
[/lua]
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:
[code]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)[/code]
We run it with:
[lua]py.RunFile("garrysmod/asdf.py")[/lua]
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.
[b]Lua[/b] Functions:
[code]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 \n and \t in your code string when necessary. So for this
function, this code is valid:
py.RunString("def asdf():\n\tprint '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).[/code]
[b]Python[/b] functions:
[code]
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.
[/code]
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.
[b]Updates:[/b]
[list]
[*]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.
[*]Removed RunReturnString and added the python function gmod.Send() for sending values to lua from python.
[*]Added back RunReturnString because in some cases it can provide functionality that gmod.Send() would be less good for doing.
[*]Added python function gmod.Set() and gmod.Run()
[*]Updated python26.dll and python26.zip to python 2.6.4 from 2.6.2.
[/list]
You can download the source [url=http://bit.ly/2bDc3h]here[/url].
Nice. Very nice. I like.
Wish I knew Python. :xd:
A dll module with which you can make dll modules :D
Haha, how fanny. XD
[QUOTE=Grocel;18063354]A dll module with which you can make dll modules :D
Haha, how fanny. XD[/QUOTE]
No?
In python, a 'module' is just another name for a python file.
You can't make .dll modules with this, please point me to where I seem to imply that you can so I can reword it, if you didn't just misread.
Can we use the html functions in this, like an exaple would be to use this module instead of gmod's http system and allow the data that python got be accessible to lua?
Something like this script?
[url]http://www.java2s.com/Code/Python/Network/SubmitPOSTData.htm[/url]
One thing you could do is like this[lua]py.RunString[[
#lolol, python in Lua
def HelloWorld():
print("Hello World!")
]][/lua]
Your syntax highlighter would probably work ok as well.
It'd be cool if you could bind the garrysmod functions to python functions so you could code for garrysmod in python. I probably wouldn't use it since I'm more used to Lua though.
[QUOTE=jonney934;18064717]Can we use the html functions in this, like an exaple would be to use this module instead of gmod's http system and allow the data that python got be accessible to lua?
Something like this script?
[url]http://www.java2s.com/Code/Python/Network/SubmitPOSTData.htm[/url][/QUOTE]
If the data it returns is either a number or a string, you should be able to do it by defining a function with RunString that takes a URL and returns the result, then call the function with RunReturnString. Maybe, lol.
JESUS CHRIST, PYTHON IN GARRY'S MOD. :byodood:
[editline]04:27PM[/editline]
Also, for those people here who are developers and do not know Python, I highly recommend learning it, as it's widely popular in the engineering arena, and you may have to use it within a job.
Garry hates python.
[QUOTE=leeetdude;18096071]Garry hates python.[/QUOTE]
Yes he does. Am I giving a crap? Nope. I don't base what I do off of garry's opinions.
I just said. I like it ;P
Oh fuck yes.
Unrestricted Python in GMod, with an interface through Lua, is pretty ingenious.
EXAMPLES OF SHIT YOU CAN DO WITH IT:
- Asynchronous Server, running on seperate thread from game
- Use the libraries of OpenCV, which include a fuckload of Webcam motion tracking stuff
- Use PyAudio/PySonic/PyAudiere etc. etc. for advanced audio processing
- Use PyGame, WX, Tk, etc., to create seperate GUIs for the game
- Using ctypes, load practically any C library (including those of Source: expose other engine functions or offer the same functionality as gm_steamworks)
- Shift over complex maths to NumPy, SciPy, etc., optionally in independent threads, since something tells me that C maths libs are gonna be quicker than doing math in pure GLua
- Other awesome python shit
Of course, how fast any of that stuff would be is debatable, since you're interacting with the Source engine through two/three interfaces, and chaining interpreted languages together.
I have no fucking idea what I'm talking about, by the way ;P
Python can't interact with the game or with lua, except for giving simple values to lua.
[QUOTE=yakahughes;18103131]Python can't interact with the game or with lua, except for giving simple values to lua.[/QUOTE]
If it can give simple values to lua, it can interact with the game.
Also, I ported one of my python scripts to it within like 5 minutes. It's really easy to run stuff which requires loops; you just add them to a Think hook or something:
[IMG]http://i23.photobucket.com/albums/b374/StupidCatOfDoom/fuckyeahitworks.jpg[/IMG]
Next step: returning the position of the face as a value GLua can use, in order to do something with it in-game I haven't quite figured out yet.
It's running a face-detection calculation every clientside Tick, so my framerate is in single-digits, but I'm pleasantly surprised it fuckin' works at all!
Here's the python code, for poops and giggles:
[code]from opencv import *
cvNamedWindow('Camera', CV_WINDOW_AUTOSIZE)
capture = Capture()
frame = capture.queryFrame()
size = cvGetSize(frame)
grayscale = cvCreateImage(size, 8, 1)
storage = cvCreateMemStorage(0)
cvClearMemStorage(storage)
cascade = cvLoadHaarClassifierCascade('haarcascade_frontalface_alt_tree.txt',cvSize(24,24))
color = cvScalar(0,255,0)
def rect(i):
cvRectangle(frame, cvPoint(i.x, i.y),
cvPoint(i.x+i.width, i.y+i.height),
color,
3,8,0)
cvCircle(frame, cvPoint(i.x+i.width/2, i.y+i.height/2),
4, color,
-1)
def render():
frame = capture.queryFrame()
cvCvtColor(frame, grayscale, CV_BGR2GRAY)
cvClearMemStorage(storage)
cvEqualizeHist(grayscale, grayscale)
faces = cvHaarDetectObjects(grayscale, cascade, storage, 1.2, 2, CV_HAAR_DO_CANNY_PRUNING, cvSize(48,48))
if faces:
map(rect, faces)
cvShowImage('Camera',frame)[/code]
Ok, pretty big update. Removed RunReturnString for this reason:
What if I run this code:
[lua]
require("python") py.Initialize()
py.RunReturnString([[7 * 8
3 + 3]])
Will it return 56 or 6? It probably will error, and this is just a bad way to do it. For this reason, I added the [b]python[/b] (not lua) function gmod.Send(). It takes 2 arguments, the first one is a number to be used as the key you are setting in a table, and the second is the value that you are setting the key of the table to. So this:
[lua]
py.RunString([[gmod.Send(1, 7 * 8)
gmod.Send(2, 3 + 3)]])
[/lua]
Would make py.PVals[1] = 56 and py.PVals[2] = 6.
The first arg must be a number. The second can be any python object, but it will only give you the actual value if it's a number or string. Anything else and it will set the key in the table to the type of object it is, for example:
[lua]py.RunString("gmod.Send(1, [2, 3, 4])")[/lua]
Would set py.PVals[1] to "List".
And to doomcat, glad someone likes this :D
But yeah what I meant was, python can't run functions in gmod or anything.
EDIT: Actually, added back RunReturnString but left in gmod.Send() because I can see some cases that RunReturnString would be better for doing some stuff than gmod.Send().
And doomcat, that's a pretty sweet thing you did there.
[QUOTE=yakahughes;18103570]But yeah what I meant was, python can't run functions in gmod or anything.[/QUOTE]
Well, if you can send vars between Python and Lua through the PVals table, can you add a call function python-side that can run Lua functions?
[QUOTE=TehDoomCat;18104087]Well, if you can send vars between Python and Lua through the PVals table, can you add a call function python-side that can run Lua functions?[/QUOTE]
You can send values from python to the lua table py.PVals, but you can't send values to python that are not coded in the string that you're running.
Which makes me wonder...
[QUOTE=yakahughes;18104176]You can send values from python to the lua table py.PVals, but you can't send values to python that are not coded in the string that you're running.
Which makes me wonder...[/QUOTE]
What if you could let the module share the memory Lua uses for storing all its variables? And then maybe have some functions to convert data between the Lua format and the Python format? Being able to read the raw Lua tables would be neat. Being able to change it would be neater ;p
Hmm... How difficult would that be to do?
You can't make them share the memory because the python state is separate from the lua state, and a python object is a totally different thing than a lua object. But I'm working on something that would be a huge help.
[QUOTE=yakahughes;18104716]You can't make them share the memory because the python state is separate from the lua state, and a python object is a totally different thing than a lua object. But I'm working on something that would be a huge help.[/QUOTE]
I think last night I was getting myself confused, yeah.
I don't really mean sharing the memory Lua uses, more like reading/writing to it from within Python.
[url=http://www.facepunch.com/showthread.php?t=520896]Jinto's old Memory Module[/url] can do some neat stuff like extending Metatables, but it occurs to me now that he never alters Lua's memory, but the source engine's heap.
Is there a way to install this into Sourcemods? The only garrymod folder there is the one containing /addons, /bin, etc. (I have a copy of Gmod in Sourcemods to test things without having to remove all my addons)
DoomCat, what was that webcam example intended to do in the long-run?
[QUOTE=Bletotum;18110091]DoomCat, what was that webcam example intended to do in the long-run?[/QUOTE]
What I'm planning to do is have it track hands [url=http://hands.slashingedge.co.uk](although I gotta train the program to do this well)[/url] for stuff like gesture recognition... starting off simple, I want to have it detect an open palm and create a pushing force away from the player at the position of the hand (webcam data translated to screen size) - a rudimentary telekenesis effect. After that... who knows? People'll have to give me ideas ;P
Right now I'm looking into quicker algorithms for detecting hands, as the Haar one's good but it can be pretty slow for realtime use, especially in a game.
holy shit, this would be awesome. ingame, blah blah blah, some minge grav guns something at you. put up your hand, ZOOM! off it goes. That would be eeeppiicckkk!!! or maby the stop-sign thing, just palm and all fingers extended would just... stop the prop in mid air, you know, set its vel to 0, and a pushing motion would send it flying. I really can't wait to see whats going to happen with your thing doom, but i hope you keep working on it.
Sounds interesting, I'm interested if you can get a wiiremote(Maybe glovepie hooked into it instead or with.) version of that.
[QUOTE=bobthe2lol;18116056]eeeppiicckkk!!![/QUOTE]
Get out.
[QUOTE=bobthe2lol;18116056]holy shit, this would be awesome. ingame, blah blah blah, some minge grav guns something at you. put up your hand, ZOOM! off it goes. That would be eeeppiicckkk!!! or maby the stop-sign thing, just palm and all fingers extended would just... stop the prop in mid air, you know, set its vel to 0, and a pushing motion would send it flying. I really can't wait to see whats going to happen with your thing doom, but i hope you keep working on it.[/QUOTE]
The stopping stuff would be nice but, you know how slow recognition programs are these days... they have like 500ms-2 seconds of delay, but to even be able to have all this work would be really cool.
Was the python module 'webcam' standard, or did you have to add it to the python26.zip/Lib folder? I just wanna know if that actually works.
[QUOTE=yakahughes;18117238]Was the python module 'webcam' standard, or did you have to add it to the python26.zip/Lib folder? I just wanna know if that actually works.[/QUOTE]
Nah, the module 'webcam' is actually how I loaded the webcam script (webcam.py) - to be able to add python funcs to a Lua hook you have to have them in the scope of the Lua script that Python's been initiliazed in.
It's based on OpenCV, [url=http://slashingedge.co.uk/dump/opencv-python.zip]the Python interface for which is here[/url] (and it probably requires you to [url=http://sourceforge.net/projects/opencvlibrary/files/opencv-win/2.0/OpenCV-2.0.0a-win32.exe/download]download OpenCV too[/url]). The python interface goes in the site-packages folder in the zip file, and works fine for me.
All my python scripts are in the root garrysmod folder, where python26.dll is located, because python's working directory is, by default, the root folder, so any files you want to import should be stuck there at first.
Of course, if you just
[code]from os import chdir
os.chdir('./garrysmod/python')[/code]
you can have a nice garrysmod/python/ folder to stick all your scripts in.
I might do a wrapper for python actually - so you can have autorun, server & client scripts, same as with Lua.
Added the python function gmod.Set(var, new value) which sets a global var in lua (first argument) to a new value (second argument).
Also added the python function gmod.Run(string lua code to run) which is like doing RunString() in lua. This lets you run lua code that runs python code that runs lua code...
Any function requests?
[QUOTE=Vir;18109916]Is there a way to install this into Sourcemods? The only garrymod folder there is the one containing /addons, /bin, etc. (I have a copy of Gmod in Sourcemods to test things without having to remove all my addons)[/QUOTE]
Put it in "steamapps/youraccount/source sdk base 2007/".
Sorry, you need to Log In to post a reply to this thread.