dietervdf
dietervdf

Reputation: 402

Running a py file through subprocess gives different output than running the file directly

I'm trying to use subprocess to generate a bunch of test cases, but something goes wrong. Why is the following (simplified example) not working?

I have a first simple program sphere.py:

#!/usr/bin/python
# -*- coding: utf-8 -*-
PI = 3.141592
radius = float(input( 'Give the radius of the sphere (in cm): ' ))

area = 4*PI*pow(radius, 2)
volume = 4/3*PI*pow(radius, 3)

print("\narea: {} cm²\nvolume: {} cm³".format(round(area,2),round(volume,2)))

Where an input of 4 results in (after running python3 sphere.py):

area: 201.06 cm²
volume: 268.08 cm³

Then I have another file, generator.py which runs the first one with subprocess:

import subprocess

res = subprocess.run(["python", "sphere.py"], input="4",
                     capture_output=True, encoding="utf")

result_lines = res.stdout.split("\n")
for line in result_lines:
    print(line)

But this results in (different volume, after running python3 generator.py):

Give the radius of the sphere (in cm): 
area: 201.06 cm²
volume: 201.06 cm³

Strangely, when I changed the volume formula to 4.0/3.0*PI*pow(radius, 3) it seemed to work fine...

What is going on here?

using Python 3.8

Upvotes: 1

Views: 107

Answers (1)

Tomerikoo
Tomerikoo

Reputation: 19431

What usually happens on systems that have both Python 2 and 3 installed, is that python command is linked to Python 2, and python3 is linked with... well obviously Python 3.

So while you are running your files from a shell with Python 3, the subprocess call invokes the Python 2 interpreter. So the easy fix is to force it to use Python 3:

subprocess.run(["python3", "sphere.py"], ...)

Or use sys.executable to make sure the same Python interpreter is being used:

import sys

subprocess.run([sys.executable, "sphere.py"], ...)

Or, find a better way to run a Python file from another one.


The hint for this problem is the difference with the division operator between Python 2 and 3. In python 2, 4/3 will give 1. While in Python 3 it will give 1.333. When you did 4.0/3.0 it forced the Python 2 interpreter to use float division as well so the problem was solved.

Interestingly, the use of 4 as the input made the two formulas equivalent (under Python 2). The 4/3 became 1 and didn't affect, and the extra power of radius became equivalent of multiplying by 4, hence the similar result.

Upvotes: 2

Related Questions