Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Running a task from inside a Python script #112

Closed
brspurri opened this issue Jan 24, 2014 · 8 comments
Closed

Running a task from inside a Python script #112

brspurri opened this issue Jan 24, 2014 · 8 comments

Comments

@brspurri
Copy link

Hi there,

I am new to invoke so please forgive my inexperience.
I am trying to set up several @tasks but I would like to be able to execute them from within a Python script.

There is plenty of excllent documentation on how to execute a task from the command line, but is this possible from within a script?

I can certainly execute a system command using invoke.runner.run('ls -la'), but if I had the task

@task
def mytask():
    run("ls -la")

how could I use invoke to call mytask from inside a script?

@leourbina
Copy link

I am having the same issue. Any ideas how to do this?

@xarg
Copy link

xarg commented Apr 20, 2014

Say you have your mytask() in task.py then to call it from say script.py:

from task import mytask

def some_func():
    mytask() 

Just call mytask() directly and it will execute all the operations inside it. No special setup should be required.

@leourbina
Copy link

Yes, but it will not execute it's dependencies if it has any. From my
reading of the source it seems likes the executor is the one that takes
care of this, however I haven't found a good way to get the executor that
is running a current task. I could create a new executor, but I would loose
the context. Let me know if I'm missing something,

-Leo
Sent from my phone, pardon my brevity
On Apr 20, 2014 4:02 AM, "Alex Plugaru" notifications@github.com wrote:

Say you have your mytask() in task.py then to call it from say script.py:

from task import mytask

def some_func():
mytask()

Just call mytask() directly and it will execute all the operations inside
it. No special setup should be required.


Reply to this email directly or view it on GitHubhttps://github.com//issues/112#issuecomment-40890116
.

@xarg
Copy link

xarg commented Apr 20, 2014

@leourbina you're right. I guess what you're looking for is something like fabric's execute: http://docs.fabfile.org/en/1.8/api/core/tasks.html?highlight=execute#fabric.tasks.execute

Unfortunately I don't think invoke has an equivalent. The closest way I could find to manage your own context is this:

from invoke import run, task, Collection
from invoke.executor import Executor
from invoke.context import Context

@task
def mytask():
    run("ls .")

def main():
    collection = Collection(mytask)
    context = Context()
    executor = Executor(collection, context)
    executor.execute("mytask")

if __name__ == '__main__':
    main()

@leourbina
Copy link

The problem with this solution is that I cannot use the built in invoke command line to list tasks, etc, and somewhat have to redo that if I were to use your solution.

One idea that comes to mind is making the executor a singleton. This way it would be trivial to implement an run_task function that takes the task name as the only argument and executes it by retrieving the current executor and calling the execute method on it. I'm not sure how hard this is, but I may try to cook something up later and submit a PR. Let me know if this makes sense,

Best,
-Leo

@xarg
Copy link

xarg commented Apr 21, 2014

@leourbina I don't see why you can't put mytask in a tasks.py file. Or in your tasks.py you can import mytask and it will be visible there. Maybe I didn't understand what you want actually, so I think it would best if you provided a more concrete example (i.e. some code).

@leourbina
Copy link

From what I gather it seems that there are three ways of running a task
from code:

Importing the task and calling it directly
This does not work as running it this way will not execute its dependencies
(or check that they have been executed). Thus, the task may not be able to
run at all as it may depend on other tasks that haven't been run yet.

Creating a new executor and calling execute on it
The main issue with this approach is that the new executor does not share
the context with the executor running the current task, and thus options
passed to the original executor (such as --echo, or --debug) are lost when
delegating the execution to the new executor. Also, creating the executor
requires specifying the name of the collection the task belongs to, but
this seems redundant.

Calling the task using invoke's run
Namely, doing from invoke import run; run("invoke mytask"). However,
that not only feels hackish but also has the same issue as the previous
solution, whereby the context and options are lost to the underlying task.

Ideally I would like an equivalent to fabric's execute, which preserves the
task execution semantics (dependencies, context, etc) while allowing me to
call tasks programmatically by name. Let me know if this clarifies your
question,

Best,
-Leo

On Mon, Apr 21, 2014 at 5:59 AM, Alex Plugaru notifications@github.comwrote:

@leourbina https://github.com/leourbina I don't see why you can't put
mytask in a tasks.py file. Or in your tasks.py you can import mytask and
it will be visible there. Maybe I didn't understand what you want actually,
so I think it would best if you provided a more concrete example (i.e. some
code).


Reply to this email directly or view it on GitHubhttps://github.com//issues/112#issuecomment-40926613
.

@bitprophet
Copy link
Member

It's totally correct that right now calling tasks from other tasks is clunky at best :(

I'm rolling this into a newer ticket I just whipped up with a bunch of dumb brainstormy things on the topic: #170

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants