EDIT: yes, if you call g.kill(), the task "contained" by g is also killed ASAP (i.e. at the first cooperative context switch) ...and, well, that's kind of the point, if you think of it.
In Gevent, this is how you'd do it:
import gevent
def task():
    for _ in range(10):
        print "processing"
        gevent.sleep(1.0)
    return 'result'
task_g = gevent.spawn(task)
res = task_g.join(timeout=3.0)
if res is None:
    print "task timed out but is continuing"
else:
    print "got result: ", res
If you instead prefer an exception based flow, you can use with_timeout; this also has the advantage that you can return None from your task and not have it confused with a timeout:
import gevent
from gevent.timeout import Timeout, with_timeout
def task():
    ...
task_g = gevent.spawn(task)
try:
    result = with_timeout(3.0, task_g.join)
except Timeout:
    print "timeout"
    result = None
else:
    print "got result:", result
Later you can still kill the task if it "totally" times out by task_g.kill().