gm_python


**gm_python**

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 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.

Download:
http://solidfiles.com/info_imgs/88ch.jpg

Examples:
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
ECHO.
ECHO ohai from python
ECHO.
PAUSE
CLS
EXIT’)]])
[/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:


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:

[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.

Lua Functions:


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).

Python functions:



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.

Updates:
[ul]
[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.

Nice. Very nice. I like.

Wish I knew Python. :xd:

A dll module with which you can make dll modules :smiley:

Haha, how fanny. XD

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?

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.

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.

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 :stuck_out_tongue_winking_eye:

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 :stuck_out_tongue_winking_eye:

Python can’t interact with the game or with lua, except for giving simple values to lua.

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:

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:


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)

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 python (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 :smiley:

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.

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?

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…

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.

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.
Jinto’s old Memory Module 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.