Is Python any good for...?

Started by
9 comments, last by assainator 10 years, 1 month ago
Hey there,

First of all, i'm sorry if it's wrong forum
since i couldn't find General Dicussion forum(maybe GameDev don't have)
and again i'm sorry.

I would like to know is Python good for
game scripting? let's say » i've a 3D game engine which is C++ programming and Python scripting.

Is it any good? I know lots of people says Lua is better with C++ but i would like to give python a try.

My questions is whats wrong with python?
I know Python is bad at calculating but i can use C++ when i need calculation.(Correct me if i'm wrong.)

Python vs Lua « which one faster?

Is Python good scripting language?

Why will someone choose Python scripting?

Good stuff about Python scripting?

Thank you.

SaiF PUNK
Advertisement

Well, having just made an app that use both lua and python from c++ code, i have to say that Lua imo is way easier to interface with c++.

Having said that, python is, imo, a much more powerfull scripting language, with more built-in functionality than lua, for example, strings manipulation, math stuffs ect. Since im no expert in either of those scripting languages, i can't really tell you more than that.

To give you an idea of what im talking about, look at my Lua interface code


#include "LuaScript.h"

CLuaScript::CLuaScript()
{
	L = NULL;
	InitLua();
}

CLuaScript::~CLuaScript()
{
	CloseLua();
}

void CLuaScript::InitLua()
{
	if(!L){
		L = lua_open();
		luaL_openlibs(L);
	}
}

void CLuaScript::CloseLua()
{
	if(L){
		lua_close(L);
		L = NULL;
	}
}

void CLuaScript::ResetLua()
{
	CloseLua();
	InitLua();
}

bool CLuaScript::LoadScriptFromFile(string scriptfile)
{
	ResetLua();

	bool value = true;

	try {
		luaL_dofile(L, scriptfile.c_str());
	} catch(...) {
		value = false;
	}

	return value;
}

bool CLuaScript::LoadScriptFromText(string scripttext)
{
	ResetLua();

	bool value = true;

	try {
		luaL_dostring(L, scripttext.c_str());
	} catch(...) {
		value = false;
	}

	return value;
}

void CLuaScript::CallFunction(string name)
{
	//call script function, 0 args, 0 retvals
	lua_getglobal(L, name.c_str());
	lua_call(L, 0, 0);
}

bool CLuaScript::SafeCallFunction(string name, char *err)
{
	//call script function, 0 args, 0 retvals
	lua_getglobal(L, name.c_str());
	int res = lua_pcall(L, 0, 0, 0);

	if(res > 0){
		const char *pErrMsg = lua_tostring(L, 1);

		if(!err){
			string Caption;
			Caption = "Lua: Error in function " + name + "().";

			MessageBox(0, pErrMsg, Caption.c_str(), MB_OK);
		} else {
			sprintf(err, "%s", pErrMsg);
		}

		return false;
	}

	return true;
}

string CLuaScript::GetGlobalString(string name)
{
	string value = "";
	try {
		lua_getglobal(L, name.c_str());
		const char *pValue = lua_tostring(L, -1);
		if(pValue)
			value = pValue;
		lua_pop(L, 1);
	} catch(...) {
	
	}

	return value;
}

void CLuaScript::SetGlobalString(string name, string value)
{
	lua_pushstring(L, value.c_str());
	lua_setglobal(L, name.c_str());
}

double CLuaScript::GetGlobalNumber(string name)
{
	double value = 0.0;
	
	try {
		lua_getglobal(L, name.c_str());
		value = lua_tonumber(L, -1);
		lua_pop(L, 1);
	} catch(...) {
	
	}

	return value;
}

void CLuaScript::SetGlobalNumber(string name, double value)
{
	lua_pushnumber(L, (int)value);
	lua_setglobal(L, name.c_str());
}

bool CLuaScript::GetGlobalBoolean(string name)
{
	bool value = false;
	
	try {
		lua_getglobal(L, name.c_str());
		value = lua_toboolean(L, -1) != 0;
		lua_pop(L, 1);
	} catch(...) {
	
	}
	
	return value;
}

void CLuaScript::SetGlobalBoolean(string name, bool value)
{
	lua_pushboolean(L, (int)value);
	lua_setglobal(L, name.c_str());
}


Clean and simple, most likely bugless, now look at the same thing for python


#include "PythonScript.h"

CPythonScript::CPythonScript()
{
	Initialized = false;
	InitPython();
}

CPythonScript::~CPythonScript()
{
	ClosePython();	
}

void CPythonScript::InitPython()
{
	if(!Initialized){
		Py_Initialize();
		module = PyImport_AddModule("__main__");
		dictionary = PyModule_GetDict(module); 
		Initialized = true;
	}
}

void CPythonScript::ClosePython()
{
	if(Initialized){
		Py_Finalize();
		module = dictionary = NULL;
		Initialized = false;
	}
}

void CPythonScript::ResetPython()
{
	ClosePython();
	InitPython();
}

bool CPythonScript::LoadScriptFromFile(string scriptfile)
{
	ResetPython();

	try {
		FILE *f = fopen(scriptfile.c_str(), "rt");
		if(f){
			PyRun_File(f, scriptfile.c_str(), Py_file_input, dictionary, dictionary);
			fclose(f);
		}
	} catch(...) {
		return false;
	}

	return true;
}

bool CPythonScript::LoadScriptFromText(string scripttext)
{
	ResetPython();

	try {
		PyRun_String(scripttext.c_str(), Py_file_input, dictionary, dictionary);
	} catch(...) {
		return false;
	}

	return true;
}

void CPythonScript::CallFunction(string name)
{
	//call script function, 0 args, 0 retvals
	PyObject* pFunc = PyObject_GetAttrString(module, name.c_str());
	PyObject_CallObject(pFunc, 0);
	//Py_DECREF(pFunc);
}

bool CPythonScript::SafeCallFunction(string name, char *err)
{
	//call script function, 0 args, 0 retvals
	PyObject* pFunc = PyObject_GetAttrString(module, name.c_str());
	if(pFunc){
		PyObject_CallObject(pFunc, 0);
		Py_DECREF(pFunc);
	}

	int have_error = PyErr_Occurred() ? 1 : 0;
	
	if(have_error){

		//const char *pErrMsg = getPythonTraceback();

		if(!err){
			string Caption;
			Caption = "Python: Error in function " + name + "().";

			//MessageBox(0, pErrMsg, Caption.c_str(), MB_OK);
		} else {
			sprintf(err, "Python: Error in function %s().", name.c_str());
		}

		return false;
	}

	return true;
}

string CPythonScript::GetGlobalString(string name)
{
	string value = "";

	PyObject* s = PyDict_GetItemString(dictionary, name.c_str());
	if(s){
		PyObject *s_Ansi = PyUnicode_AsEncodedString(s, "utf-8", "");
		const char *pValue = PyBytes_AS_STRING(s_Ansi);
		Py_DECREF(s);
		if(pValue)
			value = pValue;
	}

	return value;
}

void CPythonScript::SetGlobalString(string name, string value)
{
	PyObject *s = PyUnicode_FromString(value.c_str());
	if(s){
		PyDict_SetItemString(dictionary, name.c_str(), s);
		Py_XDECREF(s);
	}
}

/*double CPythonScript::GetGlobalNumber(string name)
{
	double value = 0.0;
	
	try {
		lua_getglobal(L, name.c_str());
		value = lua_tonumber(L, -1);
		lua_pop(L, 1);
	} catch(...) {
	
	}

	return value;
}

void CPythonScript::SetGlobalNumber(string name, double value)
{
	lua_pushnumber(L, (int)value);
	lua_setglobal(L, name.c_str());
}

bool CPythonScript::GetGlobalBoolean(string name)
{
	bool value = false;
	
	try {
		lua_getglobal(L, name.c_str());
		value = lua_toboolean(L, -1) != 0;
		lua_pop(L, 1);
	} catch(...) {
	
	}
	
	return value;
}

void CPythonScript::SetGlobalBoolean(string name, bool value)
{
	lua_pushboolean(L, (int)value);
	lua_setglobal(L, name.c_str());
}*/

/*char* getPythonTraceback()
{
    PyObject *type, *value, *traceback;
    PyObject *tracebackModule;
    char *chrRetval;

    PyErr_Fetch(&type, &value, &traceback);

    tracebackModule = PyImport_ImportModule("traceback");
    if (tracebackModule != NULL)
    {
        PyObject *tbList, *emptyString, *strRetval;

        tbList = PyObject_CallMethod(tracebackModule, "format_exception", "OOO", type, value == NULL ? Py_None : value, traceback == NULL ? Py_None : traceback);

        emptyString = PyUnicode_FromString("");
        strRetval = PyObject_CallMethod(emptyString, "join", "O", tbList);

		PyObject *strRetval_Ansi = PyUnicode_AsEncodedString(strRetval, "utf-8", "");
		chrRetval = strdup(PyBytes_AS_STRING(strRetval));
        //chrRetval = strdup(PyString_AsString(strRetval));

        //Py_DECREF(tbList);
        //Py_DECREF(emptyString);
        //Py_DECREF(strRetval);
        //Py_DECREF(tracebackModule);
    } else {
        chrRetval = strdup("Unable to import traceback module.");
    }

    //Py_DECREF(type);
    //Py_XDECREF(value);
    //Py_XDECREF(traceback);

    return chrRetval;
}*/


I pretty sure they might be bug in this last snippets(its a work in progress), but it works. Python is more complex to interface, but it's also more powerfull imo compared to lua.

Here's a script i wrote to generate a filename with 16 randoms characters, and keep the extention intact in lua


ScriptName = "Random"
InitialDirectory = ""

Input = ""
Output = ""

--------------------------------------------------------------------------------------------------------------------
-- Return the char at positon i in s
--------------------------------------------------------------------------------------------------------------------
function GetChar(s, i)
	return string.sub(s, i, i)
end

--------------------------------------------------------------------------------------------------------------------
-- Concat. 2 strings together
--------------------------------------------------------------------------------------------------------------------
function ConcatStr(s1, s2)
	return string.format("%s%s", s1, s2)
end

--------------------------------------------------------------------------------------------------------------------
-- Return the extention of a given file name
--------------------------------------------------------------------------------------------------------------------
function GetExtention(s)
	local sLen = string.len(s)

	local found = false
	local tmp = ""
	local i = sLen
	local j = 0
	while(i > 1) do
		tmp = ""
		tmp = string.sub(s, i, i)
		if(tmp == ".") then
			found = true
			break
		end
		i = i - 1;
	end;

	tmp = ""
	if(found == true) then
		while(i <= sLen) do
			tmp = tmp..string.sub(s, i, i)
			i = i + 1;
		end;
	end;

	return tmp
end


--------------------------------------------------------------------------------------------------------------------
-- Convert the file name (Called from c++)
--------------------------------------------------------------------------------------------------------------------
function Convert(FileName)
	local FileName = Input
	Output = ""

	-- Extract the file extention
	local ext = GetExtention(FileName)

	local tmp = ""
	local i = 1;
	local r = 0
	local c = ""

	while(i <= 16) do

		local k = math.random(2)
		if(k == 1) then
			r = math.random(65,90)
			c = string.char(r)
			tmp = string.format("%s%s", tmp, c)
		end
		if(k == 2) then
			r = math.random(48,57)
			c = string.char(r)
			tmp = string.format("%s%s", tmp, c)
		end

		i = i + 1
	end

	Output = string.format("%s%s", tmp, ext)

	print(Output)
end

math.randomseed(os.time())

Now, look how simple it is to do the same in python


import random, os.path

ScriptName = "Random"
InitialDirectory = ""

Input  = "Sample.avi"
Output = ""

##-------------------------------------------------------------------------------------------------------------------
##- Generate a random character
##-------------------------------------------------------------------------------------------------------------------
def GenRandChar():
    r = random.randrange(0,1)
    
    s = ""
    if(r == 0):
        s = chr(random.randrange(65, 65 + 26))
    elif(r == 1):
        s = chr(random.randrange(48, 48 + 10))

    return s

##-------------------------------------------------------------------------------------------------------------------
##- Convert the file name (Called from c++)
##-------------------------------------------------------------------------------------------------------------------
def Convert():
    global Input
    global Output
    
    FileName = ""

    for i in range(16):
        FileName = FileName + GenRandChar()

    FileExt = os.path.splitext(Input)[1]
    
    Output = FileName + FileExt



So, with that in mind, ill let you draw you're own conclusion. And for the speed question, of course a compiled language will always be faster than a scripted one, but for lua vs python, i guess you'd have to make some benchmarks.

I would like to know is Python good for
game scripting?

Well, you could use it. Python is however a language with a lot of libraries and AFAIK a relatively big standard library. You won't need most of these things as you will probably just interface with your C++ code and define simple mechanics.

I know lots of people says Lua is better with C++ but i would like to give python a try.

That's probably because Lua was made to be embedded inside your application. There are a lot of wrappers out there, also very easy-to-use ones. Python is not used for embedding this much. It's also slower (compared to LuaJIT, I don't know about the regular Lua interpreter).

I know Python is bad at calculating but i can use C++ when i need calculation.(Correct me if i'm wrong.)

A scripting language will practically always be slower than a compiled language. But you can indeed do the heavy calculations inside your C++ code.

Python vs Lua « which one faster?

As I already mentioned, LuaJIT is faster than Python. There are multiple reasons for this. For example because Lua is a simpler language (so also faster to learn). But also because Lua was so simple it was relatively easy to use JIT-compiling (compile the Lua code into assembly on run-time). When you use something like LuaJIT the calls to C++ will be the slowest. I don't know how Python handles this, but it could be slower because Python was not made to be embedded.

Is Python good scripting language?

Python is a "good" scripting language. The amount of users prove that. For an embedded scripting language, it is however slower to learn than e.g. Lua in my opinion. But it has a big community and many libraries which you may or may not need in your logic code.

I can't answer the other two questions because I don't have much experience with Python.

Hey there,

First of all, i'm sorry if it's wrong forum
since i couldn't find General Dicussion forum(maybe GameDev don't have)
and again i'm sorry.

I would like to know is Python good for
game scripting? let's say » i've a 3D game engine which is C++ programming and Python scripting.

Is it any good? I know lots of people says Lua is better with C++ but i would like to give python a try.

My questions is whats wrong with python?
I know Python is bad at calculating but i can use C++ when i need calculation.(Correct me if i'm wrong.)

Python vs Lua « which one faster?

Is Python good scripting language?

Why will someone choose Python scripting?

Good stuff about Python scripting?

Thank you.

SaiF PUNK

I don't have much experience with Lua but I have a lot of experience with python and I love it. Having said that, I would not consider using python as a scripting language that I would call from within C++. For that, I think Lua is a better fit or even javascript. I would, however, consider calling C++ from python and I think that would be a great fit.

I would not say that python is particularly slow for computation (for an interpreted language) and there are plenty of easy ways to accelerate it (although they all involve delegating the computation to C in one way or another).

-Josh

--www.physicaluncertainty.com
--linkedin
--irc.freenode.net#gdnet

Note that Python doesn't have to be as painful to embed as Vortez's code indicates. There are wrapper libraries for C++ like boost::python that make things significantly easier to work with.

One problem with Python as an embedded scripting language is that the CPython interpreter makes it very difficult to run Python scripts in a restricted execution environment (sandboxing).This isn't a big deal for some applications, but it can be a problem for games.

Thank you guys.

one question, how will this fit a game engine.

Programming language: C++

Scripting language: C++

Graphic API: DirectX

Physics Library: Not sure.

Thank you.

SaiF PUNK


Scripting language: C++

C++ is not a scripting language, at least last time i checked :)

Well, C++11 is scripting language and programming language.

Epic games have C++ scripting language in Unreal Engine 4.

The terms scripting language and programming languages really only differ in how the languages are being used -- all scripting languages are programming languages, and any programming language could potentially be used as a scripting language. So yes, you can use C++ (11 or otherwise) as a scripting language, and there are at least a couple of cases in which it has been done.

That being said, C++ is not typically used as a scripting language, and without modification it lacks a couple of the features commonly looked for in a scripting language.

Use whatever meets the needs of your project and works best for you. My instinct would be that C++ probably isn't the best choice as a scripting language (I would prefer Lua, or if you want something more similar to C++ perhaps AngelScript), but if you feel differently you absolutely can proceed, and it may well work out best for you.

Hope that helps! smile.png

- Jason Astle-Adams

Thank you jbadams.

One last question.

Is it possible to have a game engine without scripting language and add scripting language later on?

and is it possible to change scripting language from xxx to xxx?

I think it's possible but i need someone to confirm this.

Thanks

This topic is closed to new replies.

Advertisement