I was a little addicted to the subprocess, so I made a note.
While creating the helper script for deployment, processing equivalent to cp -pr was required. The (incomplete) cp implementation written in Python is as follows.
python_cp
def _copy(src, dst):
if os.path.isfile(src):
shutil.copy2(src, dst)
return
if os.path.isdir(src) and os.path.isdir(dst):
target = os.path.join(dst, os.path.basename(src))
# TODO Fix behavior like cp -pr (If the target directory exists, the files under it/Directory should be preserved)
if os.path.exists(target):
shutil.rmtree(target)
shutil.copytree(src, target)
return
if os.path.isdir(src) and os.path.isfile(dst):
raise IOError(
"(Src:directory/Dest:file) This combination isn't allowed")
Although there are restrictions (see comments), that case could not occur in this application, so it's OK.
However, as usual, I heard the hallucination that "Wow, the engineer (laughs) who doesn't do it even though I can move cp with Subprocess ..." from the side, so I decided to write an implementation that uses subprocess. ..
subprocess_cp_error
def _copy(src, dst):
subprocess.Popen(['cp', '-pr', src, dst]).communicate()
However, with this implementation, wildcards cannot be used in src. To interpret the wildcard, you need to pass shell = True to Popen and execute the command through the shell. http://docs.python.jp/2.7/library/subprocess.html#subprocess.Popen
subprocess_cp_error2
def _copy(src, dst):
subprocess.Popen(['cp', '-pr', src, dst], shell=True).communicate()
So, I thought, "Is this Finish?", But that's not the case. With the above implementation, the cp command doesn't work at all. When shell = True, the command is executed via the shell as described above, but it is equivalent to the following command.
via_shell_error
/bin/sh -c 'cp' '-pr' (src) (dst)
At first glance, it looks good, but in this case -pr is not considered as an option for cp, and src and dst are not considered as arguments for cp. In other words, cp was executed without any arguments, resulting in an error. To be correct, you have to specify it with one character string as follows
via_shell
/bin/sh -c 'cp -pr (src) (dst)'
So, to execute the corresponding subprocess, specify the command given to Popen as a character string instead of an array.
subprocess_cp
def _copy(src, dst):
subprocess.Popen('cp -pr {0} {1}'.format(src, dst), shell=True).communicate()
Should not be shell = True if not needed w Well, in fact, it also causes shell injection, so the library reference also says, "When using external input, never set it to True!" ...
Recommended Posts