0

I've been trying to run a Java program and capture it's STDOUT output to a file from the Python script. The idea is to run test files through my program and check if it matches the answers.

Per this and this SO questions, using subprocess.call is the way to go. In the code below, I am doing subprocess.call(command, stdout=f) where f is the file I opened.

The resulted file is empty and I can't quite understand why.

import glob

test_path = '/path/to/my/testfiles/'
class_path = '/path/to/classfiles/'
jar_path = '/path/to/external_jar/'
test_pattern = 'test_case*'
temp_file = 'res'

tests = glob.glob(test_path + test_pattern) # find all test files

for i, tc in enumerate(tests):
    with open(test_path+temp_file, 'w') as f:
        # cd into directory where the class files are and run the program
        command = 'cd {p} ; java -cp {cp} package.MyProgram {tc_p}'
                                                 .format(p=class_path,
                                                         cp=jar_path,
                                                         tc_p=test_path + tc)
        # execute the command and direct all STDOUT to file
        subprocess.call(command.split(), stdout=f, stderr=subprocess.STDOUT)
    # diff is just a lambda func that uses os.system('diff')
    exec_code = diff(answers[i], test_path + temp_file)
    if exec_code == BAD:
        scream(':(')
Community
  • 1
  • 1
Aza T
  • 589
  • 4
  • 11
  • there are many reasons for your file to be empty first...execute the commands by replacing the variable with actual values in your command line and see if you're using correct command!! – Nishanth Matha Nov 28 '16 at 05:01
  • I've tried it, and the command was correct. I also tried using w/o splitting the command and passing in ```shell=True```. I've also tried ```subprocess.check_call(command.split(), stdout=PIPE)``` and the status was 0 (success). – Aza T Nov 28 '16 at 05:03
  • do you've write access to that file/directory? – Nishanth Matha Nov 28 '16 at 05:05
  • I suppose so, because of the ```with open as```. This should give me write access. – Aza T Nov 28 '16 at 05:09

1 Answers1

0

I checked the docs for subprocess and they recommended using subprocess.run (added in Python 3.5). The run method returns the instance of CompletedProcess, which has a stdout field. I inspected it and the stdout was an empty string. This explained why the file f I tried to create was empty.

Even though the exit code was 0 (success) from the subprocess.call, it didn't mean that my Java program actually got executed. I ended up fixing this bug by breaking down command into two parts.

If you notice, I initially tried to cd into correct directory and then execute the Java file -- all in one command. I ended up removing cd from command and did the os.chdir(class_path) instead. The command now contained only the string to run the Java program. This did the trick.

So, the code looked like this:

good_code = 0
# Assume the same variables defined as in the original question 
os.chdir(class_path) # get into the class files directory first
for i, tc in enumerate(tests):
    with open(test_path+temp_file, 'w') as f:
        # run the program
        command = 'java -cp {cp} package.MyProgram {tc_p}'
                                                    .format(cp=jar_path,
                                                     tc_p=test_path + tc)
        # runs the command and redirects it into the file f
        # stores the instance of CompletedProcess
        out = subprocess.run(command.split(), stdout=f)
        # you can access useful info now
        assert out.returncode == good_code
Aza T
  • 589
  • 4
  • 11