The Python Oracle

Any way to execute a piped command in Python using subprocess module, without using shell=True?

--------------------------------------------------
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: Puzzle Game 5 Looping

--

Chapters
00:00 Any Way To Execute A Piped Command In Python Using Subprocess Module, Without Using Shell=True?
00:55 Answer 1 Score 25
01:18 Answer 2 Score 2
01:35 Accepted Answer Score 3
01:55 Answer 4 Score 1
02:08 Thank you

--

Full question
https://stackoverflow.com/questions/4368...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #bash

#avk47



ANSWER 1

Score 25


If you want to avoid using shell=True, you can manually use subprocess pipes.

from subprocess import Popen, PIPE
p1 = Popen(["tar", "-cvf", "-", "path_to_archive"], stdout=PIPE)
p2 = Popen(["split", "-b", "20m", "-d", "-a", "5", "-", "'archive.tar.split'"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]

Note that if you do not use the shell, you will not have access to expansion of globbing characters like *. Instead you can use the glob module.




ACCEPTED ANSWER

Score 3


tar can split itself:

tar -L 1000000 -F name-script.sh cf split.tar largefile1 largefile2 ...

name-script.sh

#!/bin/bash
echo "${TAR_ARCHIVE/_part*.tar/}"_part"${TAR_VOLUME}".tar >&"${TAR_FD}"

To re-assemble

tar -M -F name-script.sh cf split.tar

Add this to your python program.




ANSWER 3

Score 2


Is there any reason you can't use tarfile? | http://docs.python.org/library/tarfile.html

import tarfile
tar = tarfile.open("sample.tar.gz")
tar.extractall()
tar.close()

Just write like a file like object using tarfile rather than invoking subprocess.




ANSWER 4

Score 1


Shameless plug, I wrote a subprocess wrapper for easier command piping in python: https://github.com/houqp/shell.py

Example:

shell.ex("tar -cvf - path_to_archive") | "split -b 20m -d -a 5 - 'archive.tar.split'"