icn
icn

Reputation: 17876

How can I specify working directory for a subprocess

Is there a way to specify the running directory of command in Python's subprocess.Popen()?

For example:

Popen('c:\mytool\tool.exe', workingdir='d:\test\local')

My Python script is located in C:\programs\python

Is is possible to run C:\mytool\tool.exe in the directory D:\test\local?

How do I set the working directory for a sub-process?

Upvotes: 257

Views: 292908

Answers (2)

ashrasmun
ashrasmun

Reputation: 566

Other way is to simply do this

cwd = os.getcwd()
os.chdir('c:\some\directory')
subprocess.Popen('tool.exe')
os.chdir(cwd)

This solution works if you want to rely on relative paths, for example, if your tool's location is c:\some\directory\tool.exe. cwd keyword argument for Popen will not let you do this. Some scripts/tools may rely on you being in the given directory while invoking them. To make this code less noisy, aka detach the logic related to changing directories from the "business logic", you can use a decorator.

def invoke_at(path: str):
    def parameterized(func):
        def wrapper(*args, **kwargs):
            cwd = os.getcwd()
            os.chdir(path)

            try:
                ret = func(*args, **kwargs)
            finally:
                os.chdir(cwd)

            return ret

        return wrapper

    return parameterized            

Such decorator can be then used in a way:

@invoke_at(r'c:\some\directory')
def start_the_tool():
    subprocess.Popen('tool.exe')

Upvotes: 14

Mark Rushakoff
Mark Rushakoff

Reputation: 258358

subprocess.Popen takes a cwd argument to set the Current Working Directory; you'll also want to escape your backslashes ('d:\\test\\local'), or use r'd:\test\local' so that the backslashes aren't interpreted as escape sequences by Python. The way you have it written, the \t part will be translated to a tab.

So, your new line should look like:

subprocess.Popen(r'c:\mytool\tool.exe', cwd=r'd:\test\local')

To use your Python script path as cwd, import os and define cwd using this:

os.path.dirname(os.path.realpath(__file__)) 

Upvotes: 375

Related Questions