With a django project, you get a script called manage.py, which has a bunch of subcommands such as runserver, migrate, etc. You can get a list of them all by running the script with no arguments.

My plan is to parse that output, and use it to power TAB completion after . manage.py, and also set up aliases, so I can just type migr[TAB] instead of ./manage.py migrate.

My problem is that because it's Python, and it needs to load in all the django machinery to show the subcommands, I'm waiting about a half second every time, on a really small project. The larger the project, the longer it takes.

My idea was to run the interrogation of the script, definition of aliases, and setup of autocompletion, in a background task a la

(for subcommand in parse_manage_py; do alias $subcommand='./manage.py $subcommand'; done) &

But that doesn't set any variables in the parent shell. I mucked around with export for a while before I figured out that exports "downwards" instead of "upwards".


One (inelegant) approach could be to redirect the output of an asynchronous process (that does the slow work) to a file and use the content of that file only when you first need it. You can do things in the meantime. For instance:

# placing everything into a function only because it easier to test
function func {
    # Test (I think that "runserver" is one of the alias you should get)
    echo -n "start: "
    alias -p|grep -q runserver && \
        echo \"runserver\" is defined || \
            echo \"runserver\" is NOT defined

    # prepare the aliases in background
    ( python ./manage.py | \
          sed -n 's/^    \(.*\)/alias \1=".\/manage.py \1"/p'
      sleep 2  # simulate slow process
    ) >$f &

    # here you can do things...
    echo "I'm doing thing..."
    sleep 1
    echo "...finished my things. Waiting for the aliases"

    # but if you need the aliases you must check that they are ready
    wait $slow_process_id
    source $f
    rm -f $f
    echo "Aliases ready :-)"

    # Test again
    echo -n "end: "
    alias -p|grep -q runserver && \
        echo \"runserver\" is defined || \
            echo \"runserver\" is NOT defined

Please see also coproc ... command ..., but I think its filehandles disappear when the command it terminated.

I've also tried two wrong approaches: first I tried to have my script source some alias definitions from a subprocess, but, of course these aliases did not make to the calling shell. The problem here is that & spawns a subshell.

Then I tried to use indirection. The problem here is that "indirect" variables are not special and they are separated from the calling shell.

Thanks G-Man for the useful comments.

  • 1
    You haven’t tried this, have you? – G-Man Says 'Reinstate Monica' Jan 29 '18 at 16:48
  • you're right, sorry. I had the aliases in my shell from previous experiments. Should I delete the post? – Matteo Gamboz Jan 30 '18 at 7:58
  • It’s your decision.  If I discover that an answer I have posted is fundamentally flawed and unrecoverable, I often delete it — although sometimes I leave it there, so people can see that that approach has been tried and led to a blind alley.  On the other hand, you seem to have made some progress in coming up with answers that do work — although, on the third hand, I don’t see exactly how your mktemp solution is any better that the original . manage.py, … (Cont’d) – G-Man Says 'Reinstate Monica' Jan 30 '18 at 16:36
  • (Cont’d) …  since you still leave the user’s terminal (and shell) unusable until the long-running process is done. (Also, if [[ -n "$(cat $f)" ]] is a terrible way to check whether the long-running process is done; all it does is check whether the process has written any output, and you can do that more simply with -s "$f".) Do you want to try to improve on that?  Do you believe that you can devise a working solution based on coproc? … (Cont’d) – G-Man Says 'Reinstate Monica' Jan 30 '18 at 16:36
  • (Cont’d) …  If you don’t delete the answer, I would suggest that you clean up the bottom half.  The question isn’t about process substitution, here documents, indirect variables, or eval, so there’s no real point in talking about them if they don’t lead to an answer.  It might be useful to leave the statement that you tried . manage.py & and it didn’t work (and explain why), and leave it at that.  I’ll withdraw my downvote and let you decide.  … (Cont’d) – G-Man Says 'Reinstate Monica' Jan 30 '18 at 16:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.