Search code examples
pythonpython-2.7subprocesspopen

What is the correct way to use stdin, stdout, and stderr in Python 2.7?


Does anyone have experience using the subprocess.call command in Python? I keep getting errors whenever a line like this is in my code:

INFILE1 = open(script_dir+"/Scripts/plot_TSS_profile.R","r")
  subprocess.call("Rscript","--slave","--args",filenames["housekeeping_profile"]+" "+filenames["unexpressed_profile"]+" "+filenames["profile_plot"],stdin=INFILE1,  stderr=ERR_LOG,stdout=OUT_LOG,shell=True)
   INFILE1.close(). 

If I leave the code as is, I get an error that the program finds multiple values for each th stdin, stderr, and stdout for some reason even though those are the only ones in the code. If I take out these parameters and just put the infile early in the brackets after “--args”, it doesn’t seem to read the file as it says the ‘buffer should be an integer.’

For example, this way gives the buffer error:

INFILE1 = script_dir+"/Scripts/plot_TSS_profile.R"
    subprocess.call("Rscript",INFILE1,"--slave","--args",filenames["housekeeping_profile"]+" "+filenames["unexpressed_profile"]+" "+filenames["profile_plot"],stderr=ERR_LOG,shell=True)
    INFILE1.close()

Here are my error outputs for more specific information:

The one on buffsize:

Traceback (most recent call last): File "/mnt/work1/users/pughlab/projects/IEG_MiSEQ/Inferring_DNA_Expression/ExpressionPrediction-master/expression_prediction.py", line 277, in

    step5(ERR_LOG,OUT_LOG,args,proj_dir,script_dir,filenames)
  File "/mnt/work1/users/pughlab/projects/IEG_MiSEQ/Inferring_DNA_Expression/ExpressionPrediction-master/expression_prediction.py", line 165, in step5
    subprocess.call("Rscript",INFILE1,"--slave","--args",filenames["housekeeping_profile"]+" "+filenames["unexpressed_profile"]+" "+filenames["profile_plot"],stderr=ERR_LOG,shell=True)
  File "/mnt/work1/software/centos7/python/2.7.15/lib/python2.7/subprocess.py", line 172, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/mnt/work1/software/centos7/python/2.7.15/lib/python2.7/subprocess.py", line 343, in __init__
    raise TypeError("bufsize must be an integer")
TypeError: bufsize must be an integer

And the other error on there being multiple values:

 Traceback (most recent call last):
  File "/mnt/work1/users/pughlab/projects/IEG_MiSEQ/Inferring_DNA_Expression/ExpressionPrediction-master/expression_prediction.py", line 272, in <module>
    step5(ERR_LOG,OUT_LOG,args,proj_dir,script_dir,filenames)
  File "/mnt/work1/users/pughlab/projects/IEG_MiSEQ/Inferring_DNA_Expression/ExpressionPrediction-master/expression_prediction.py", line 165, in step5
    subprocess.call("Rscript","--slave","--args",filenames["housekeeping_profile"]+" "+filenames["unexpressed_profile"]+" "+filenames["profile_plot"],stdin=INFILE1,stderr=ERR_LOG,stdout=OUT_LOG,shell=True)
  File "/mnt/work1/software/centos7/python/2.7.15/lib/python2.7/subprocess.py", line 172, in call
    return Popen(*popenargs, **kwargs).wait()
TypeError: __init__() got multiple values for keyword argument 'stdin'

Thank you


Solution

  • The main problem is that call takes a list of arguments or a single string to be parsed by the shell. You don't appear to need shell=True here; just create a single list of all the positional arguments you attempting to pass.

    with open(script_dir+"/Scripts/plot_TSS_profile.R","r") as INFILE1:
        cmd = [
            "Rscript",
            "--slave",
            "--args",
            filenames["housekeeping_profile"], 
            filenames["unexpressed_profile"],
            filenames["profile_plot"]
        ]
        subprocess.call(cmd, stdin=INFILE1, stderr=ERR_LOG, stdout=OUT_LOG)
    

    Passing multiple positional arguments means that parameters that were meant to be set via keyword arguments (like stdin, etc) are being assigned values that were meant as part of the command to execute.