I spend a few hours writing a little script.
Basically what it does is create a new text file and fills it up with whatever.
I zip the text file --using zipfile-- and here's where my problem lies.
I want to run the Windows system command:
copy /b "imgFile.jpg" + "zipFile.zip" newImage.jpg
To merge the image "imgFile.jpg" and the zip "zipFile.zip".
So:
os.system("copy /b \"imgFile.jpg\" + \"zipFile.zip\" newImage.jpg")
When I run my script, it all seems to go fine.
But when it's done and I try to extract the 'newImage.jpg' file, it gives me:
The archive is either in unknown format or damaged
This ONLY happens when I run the system command within the script.
It works fine when I use the shell. It even works if I use a separate script.
I've double checked my zip file. Everything is in good shape.
Is there something I'm doing wrong? Something I'm not seeing?
Have you tried using shutil?
import shutil
shutil.copy(src, dst)
There may be a problem with the way Python is passing the arguments to the shell command. Try using subprocess.call. This method takes arguments as an array and passes them that way to the command:
import subprocess
subprocess.call(["copy", "/b", '"imgFile.jpg" + "zipFile.zip"', "newImage.jpg"])
Related
I try to automatise an image stitching process from python using the software PTGui.
I can execute the following command which works perfectly in the windows command line :
C:\Users\mw4168> "C:\Program Files\PTGui\ptgui.exe" -batch "C:\Users\mw4168\OneDrive\Desktop\PTGui Tests\3 rows\Panorama.pts"
command screenshot here
However, when I try to execute this command using os.system or subprocess.run in Python:
import os
os.system("C:\Program Files\PTGui\ptgui.exe" + "-batch" +"C:\Users\mw4168\OneDrive\Desktop\PTGui Tests\3 rows\panorama.pts")
I get this error :
'C:\Program' is not recognized as an internal or external command, operable program or batch file.
error screenshot here
It seems that there is an issue with the spaces within the string... Any idea on how to fix this?
Thanks a lot in advance,
Paul
Like the os.system documentation already tells you, a better solution altogether is to use subprocess instead.
subprocess.run([
r"C:\Program Files\PTGui\ptgui.exe",
"-batch",
r"C:\Users\mw4168\OneDrive\Desktop\PTGui Tests\3 rows\panorama.pts"])
The string you created also lacked spaces between the indvidual arguments; but letting Python pass the arguments to the OS instead also gives you more control over quoting etc.
The issue is that you're probably (as you have posted no code) not passing the C:\Program Files\PTGui\ptgui.exe as a string to the terminal but just a plain command
Use
import os
os.system('\"C:\Program Files\PTGui\ptgui.exe\" -batch')
I am doing a script using SoX to merge multiple audio file together.
This command works in the terminal
sox &(ls *.mp3) out.mp3
but if I try using it inside a python script by calling subprocess.run() it doesn't
subprocess.run(['sox', '$(ls *.mp3)', 'out.mp3'])
> sox FAIL formats: can't open input file `$(ls *.mp3)': No such file or
> directory
I image that is because of the subshell operation, but I don't know how to pass it correctly.
I also tried, as some other post suggested, passing the argument shell=True but then it says
> sox FAIL sox: Not enough input filenames specified
I am in the same working directory and I also tried supplying the full path but doesn't work either.
I could just write a bash script and call it, but I would like to know how to deal in this scenario with Python.
you want to use shell=True to force subprocess to run your command through the shell interpreter and parse the wildcards/sub-commands. However this (depending on the platform) imposes that the argument is passed as string, not as list of parameters. A lot of constraints for a lazy & unsafe way of doing it.
Wait. You can do without shell=True using glob.glob:
subprocess.run(['sox'] + glob.glob('*.mp3') + ['out.mp3'])
Would be better to check if there actually are mp3 files in the current folder so:
input_files = glob.glob('*.mp3')
if input_files:
subprocess.run(['sox'] + input_files + ['out.mp3'])
else:
raise Exception("No mp3 files")
if you get the "No mp3 files" message, then check the current directory. It's always good to use a parameter for the input directory, and avoid relying on the current directory (glob.glob(os.path.join(input_directory,'*.mp3')))
I am trying to make a python script that will open a directory, apply a perl script to every file in that directory and get its out put in either multiple text files or just one.
I currently have:
import shlex, subprocess
arg_str = "perl tilt.pl *.pdb > final.txt"
arg = shlex.split(arg_str)
import os
framespdb = os.listdir("prac_frames")
for frames in framespdb:
subprocess.Popen(arg, stdout=True)
I keep getting *.pdb not found. I am very new to all of this so any help trying to complete this script would help.
*.pdb not found means exactly that - there won't be a *.pdb in whatever directory you're running the script... and as I read the code - I don't see anything to imply it's within 'frames' when it runs the perl script.
you probably need os.chdir(path) before the Popen.
How do I "cd" in Python?
...using a python script to run somewhat dubious syscalls to perl may offend some people but everyone's done it.. aside from that I'd point out:
always specify full paths (this becomes a problem if you will later say, want to run your job automatically from cron or an environment that doesn't have your PATH).
i.e. 'which perl' - put that full path in.
./.pdb would be better but not as good as the fullpath/.pdb (which you could use instead of the os.chdir option).
subprocess.Popen(arg, stdout=True)
does not expand filename wildcards. To handle your *.pdb, use shell=True.
i need some help with this...
I have a program installed on my computer that i want to call to calculate some things and give me an output-file...
in Matlab the command "dos()" does the job giving me also the cmd screen output in matlab.
I need this to work in python but i am making something wrong.
data='file.csv -v'
db=' -d D:\directory\bla\something.db'
anw='"D:\Program Files\bla\path\to\anw.exe"' + db + ' -i' + data
"anw" output is this one:
>>> anw
'"D:\\Program Files\\bla\\path\\to\\anw.exe" -d D:\\directory\\bla\\something.db -i file.csv -v'
## without the "" it does not work either
import subprocess as sb
p= sb.Popen('cmd','/K', anw) ## '/C' does not work either
i get the following error message from cmd.exe inside the python shell
Windows cannot find "\"D:\Program Files\bla\path\to\anw.exe"" Make sure you typed the name correctly, and then try again.
this line runs when i make a bat. file out of it.
it runs in matlab via "dos(anw)" so what is wrong here?
ps: i have blanks in my command... could this be the problem? i do not know where the first "\" comes from in the cmd. exe error message
for now i created a bat. file with all the stuff cmx.de should do in the specific directory where the input file lies...
i just had to tell python to change directory with
import os
os.chdir("D:\working\directory")
os.system(r'D:\working\directory\commands.bat')
it works good and gives me the output of cmd directly in the python shell
I'm trying to to a ls -l from python, to check for the last modification date of a file.
os.listdir doesn't show the long list format.
subprocess.call shows the format, but actually prints it, and returns 0. I want to be able to put it in a variable. Any ideas ?
Also, I tried
subprocess.call("ls","*.py")
which answers
ls: cannot access *.py: No such file or directory
it works with shell=True, but if someone could explain why it doesn't work without it, I'll appreciate. If you know how to make it work, even better.
It doesn't work without shell=True because the * is a shell expansion character - going from *.py to a list of files ending in .py is a function performed by the shell itself, not ls or python.
If you want to get the output of a command invoked via subprocess, you should use subprocess.check_output() or subprocess.Popen.
ls_output = subprocess.check_output(['ls', '-l'])
With nice formatting:
import subprocess
print(subprocess.check_output(['ls', '-lh']).decode('utf-8'))