Original comparison. The shell form is a description, not a program. Safe pattern, also saved as safe-print.py: subprocess.run(["printf", "%s", "club-note"], check=True, shell=False) The program name is printf. The next item is the format. The last item is the value club-note, one argument. shell stays false, so this call does not start a shell parser. Shell form, not saved as a program and not to be typed: one string would hold the program and the value together a shell would parse that string as a command line characters that are syntax to that shell would not stay plain data Predicted result of the safe call, not observed: the process writes club-note and nothing else