I have been going through "A byte of Python" to learn the syntax and methods etc...
I have just started with a simple backup script (straight from the book):
#!/usr/bin/python
# Filename: backup_ver1.py
import os
import time
# 1. The files and directories to be backed up are specified in a list.
source = ['"C:\\My Documents"', 'C:\\Code']
# Notice we had to use double quotes inside the string for names with spaces in it.
# 2. The backup must be stored in a main backup directory
target_dir = 'E:\\Backup' # Remember to change this to what you will be using
# 3. The files are backed up into a zip file.
# 4. The name of the zip archive is the current date and time
target = target_dir + os.sep + time.strftime('%Y%m%d%H%M%S') + '.zip'
# 5. We use the zip command to put the files in a zip archive
zip_command = "zip -qr {0} {1}".format(target, ' '.join(source))
# Run the backup
if os.system(zip_command) == 0:
print('Successful backup to', target)
else:
print('Backup FAILED')
Right, it fails. If I run the zip command in the terminal it works fine. I think it fails because the zip_command is never actually run. And I don't know how to run it.
Simply typing out zip_command does not work. (I am using python 3.1)
Are you sure that the Python script is seeing the same environment you have access to when you enter the command manually in the shell? It could be that zip isn't on the path when Python launches the command.
It would help us if you could format your code as code; select the code parts, and click on the "Code Sample" button in the editor toolbar. The icon looks like "101/010" and if you hold the mouse pointer over it, the yellow "tool tip" box says "Code Sample <pre></pre> Ctrl+K"
I just tried it, and if you paste code in to the StackOverflow editor, lines with '#' will be bold. So the bold lines are comments. So far so good.
Your strings seem to contain backslash characters. You will need to double each backslash, like so:
target_dir = 'E:\\Backup'
This is because Python treats the backslash specially. It introduces a "backslash escape", which lets you put a quote inside a quoted string:
single_quote = '\''
You could also use a Python "raw string", which has much simpler rules for a backslash. A raw string is introduced by r" or r' and terminated by " or ' respectively. examples:
# both of these are legal
target_dir = r"E:\Backup"
target_dir = r'E:\Backup'
The next step I recommend is to modify your script to print the command string, and just look at the string and see if it seems correct.
Another thing you can try is to make a batch file that prints out the environment variables, and have Python run that, and see what the environment looks like. Especially PATH.
Here is a suggested example:
set
echo Trying to run zip...
zip
Put those in a batch file called C:\mytest.cmd, and then have your Python code run it:
result_code = os.system("C:\\mytest.cmd")
print('Result of running mytest was code', result_code)
If it works, you will see the environment variables printed out, then it will echo "Trying to run zip...", then if zip runs it will print a message with the version number of zip and how to run it.
zip command only work in linux not for windows.. thats why it make an error..
Related
I have made a program with which I download all my songs as mp3, however, unless I use the default name, it doesnt get saved as "song.mp3" but rather "song". Someone online suggested this :
for /R %x in (*) do ren "%x" *.mp3
But this also replaces the program's extension. converter.py now reads as converter.mp3
To make this easier and not have to rename the files all at once, I thought I would integrate this into the code by using the os module. But then the code wouldn't run the next time.
Is there a way to add a 'not' operator or something of the like so that the code replaces all extensions with '.mp3' except '.py'
What I have currently added to the program :
os.system('for /R %x in (*) do ren "%x" *.mp3')
os.system('ren converter.mp3 converter.py')
I feel like this would be easier to fix at download time rather than afterwards... but
for item in os.listdir():
if os.path.isfile(item) and not item.endswith('.py'):
os.rename(item, item + '.mp3')
Hey all having a little issue with my code. I am creating a random food picker for my girlfriend whenever she tells me that she doesn't know where to eat
I am using aiys voice kit on a raspberry pi zero w and cloud text to speech API so the command process is like this
--- User Presses button
"Cloud speech is listening"
User Says "Where should we go for food"
run rndfoodpkr() ---
I also tried using omxplayer instead of mixer
def rndfoodpkr():
randomfile= random.choice(os.listdir(/home/pi/share/Programs/FoodPicker/Food/"))
file = '/home/pi/share/Programs/FoodPicker/Food' + randomfile + '/'
os.system ('mixer' + file)
rndfoodpkr() is supposed to run and select a random file inside the Food folder then mixer/omxplayer is supposed to run and play the .mp3 file however it gives this error
"sh: 1: mixer/home/pi/share/Programs/FoodPicker/Food/Wendys.mp3/: not found"
Same results for any file ie. Tacobell, McDonalds, arbys, etc
try:
file = '/home/pi/share/Programs/FoodPicker/Food' + randomfile
os.system ('mixer ' + file)
I see three problems with this code:
There is a quotation mark missing before /home on the second line. I suspect you introduced this error when posting your question, as your program would not be running at all if this error were present.
You are inserting a slash in the wrong place when you generate file -- the path you end up generating would look like
/home/pi/share/Programs/FoodPicker/FoodFilename.mp3/
^^ ^
instead of the intended
/home/pi/share/Programs/FoodPicker/Food/Filename.mp3
^ ^
A neat way of fixing this would be to assign the path to a variable instead of including it in your program twice, then use os.path.join() to combine the path components, e.g:
path = "/home/pi/share/Programs/FoodPicker/Food"
randomfile = os.path.join(path, random.choice(os.listdir(path)))
You are not including a space between the command mixer and the filename. Add one:
os.system("mixer " + randomfile)
^^^
Why are you suffixing the file name with a / character? That's possibly telling whatever application you're passing it to that it's a directory (so it could, for example, play every file in that directory - no necessarily the case but it certainly wouldn't be totally bizarre behavior).
See for example, the following transcript:
>> touch wendy.mp3
>> aplay wendy.mp3/ # Note the / at the end.
wendy.mp3/: Not a directory
In any case, I suspect the problem may be the missing / between the path and the file name, and the missing space between the command and the argument. That's likely to give you a full command of:
mixer/home/pi/share/Programs/FoodPicker/FoodWendys.mp4
So the first think I would try would be to move the / to where it belongs and put the space in, something like:
cmd = 'mixer /home/pi/share/Programs/FoodPicker/Food/{}'.format(randomfile)
cmd = 'mixer {}'.format(os.path.join('/home/pi/share/Programs/FoodPicker', randomfile))
The latter (with os.path.join) is considered more portable.
If your code still doesn't work after making those changes (or you want to debug), just print out the command before using it:
print("Command is '{}'".format(cmd))
A great many problems can be solved just by looking at what the computer is seeing(1).
(1) This also works for wives, apparently :-)
I found a solution myself that works great
def rndfoodpkr ():
path = "/home/pi/share/Programs/FoodPicker/Food"
randomfile = os.path.join(path, random.choice(os.listdir(path)))
mixer.init()
mixer.music.load(randomfile)
mixer.music.play()
Thank you guys for the help!
I'm trying to call 'sed' from Python and having troubles passing the command line via either subprocess.check_call() or os.system().
I'm on Windows 7, but using the 'sed' from Cygwin (it's in the path).
If I do this from the Cygwin shell, it works fine:
$ sed 's/ /\ /g' <"C:foobar" >"C:foobar.temp"
In Python, I've got the full pathname I'm working with in "name". I tried:
command = r"sed 's/ /\ /g' " + "<" '\"' + name + '\" >' '\"' + name + '.temp' + '\"'
subprocess.check_call(command, shell=True)
All the concatenation is there to make sure I have double quotes around the input and output filenames (in case there are blank spaces in the Windows file path).
I also tried it replacing the last line with:
os.system(command)
Either way, I get this error:
sed: -e expression #1, char 2: unterminated `s' command
'amp' is not recognized as an internal or external command,
operable program or batch file.
'nbsp' is not recognized as an internal or external command,
operable program or batch file.
Yet, as I said, it works OK from the console. What am I doing wrong?
The shell used by subprocess is probably not the shell you want. You can specify the shell with executable='path/to/executable'. Different shells have different quoting rules.
Even better might be to skip subprocess altogether, and write this as pure Python:
with open("c:foobar") as f_in:
with open("c:foobar.temp", "w") as f_out:
for line in f_in:
f_out.write(line.replace(' ', ' '))
I agree with Ned Batchelder's assessment, but think what you might want to consider using the following code because it likely does what you ultimately want to accomplish which can be done easily with the help of Python's fileinput module:
import fileinput
f = fileinput.input('C:foobar', inplace=1)
for line in f:
line = line.replace(' ', ' ')
print line,
f.close()
print 'done'
This will effectively update the given file in place as use of the keyword suggests. There's also an optional backup= keyword -- not used above -- which will save a copy of the original file if desired.
BTW, a word of caution about using something like C:foobar to specify the file name because on Windows it means a file of that name in whatever the current directory is on drive C:, which might not be what you want.
I think you'll find that, in Windows Python, it's not actually using the CygWin shell to run your command, it's instead using cmd.exe.
And, cmd doesn't play well with single quotes the way bash does.
You only have to do the following to confirm that:
c:\pax> echo hello >hello.txt
c:\pax> type "hello.txt"
hello
c:\pax> type 'hello.txt'
The system cannot find the file specified.
I think the best idea would be to use Python itself to process the file. The Python language is a cross-platform one which is meant to remove all those platform-specific inconsistencies, such as the one you've just found.
I wrote this code and it is failing at line 11 on the "target_dir" command with invalid syntax I have a vm ubuntu and I just copy and pasted the code and it worked there but not in my win7 and I am not sure why. I was reading another question with similar code but it had a different error and noticed that someone said that some of these commands where obsolete so I was just wondering if that is so and I would just drop this book and move on to another one i just got.
Thanks in advance for the help,
# Filename: backup_ver1.py
import os
import time
# 1. The files and directories to be backed up are specified in a list.
source = ['"D:\\Warlock"', 'C:\\Druid'
# Notice we had to use double quotes inside the string for names with spaces in it.
# 2. The backup must be stored in a main backup directory
target_dir = r'C:\Backup' # Remember to change this to what you will be using
# 3. The files are backed up into zip file.
# 4. The name of the zip archive is the current date and time
target = target_dir + os.sep + time.strftime('%Y%m%d%H%M%S') + '.zip'
# 5. We use the zip commnad to put the files in a zip archive
zip_commnad = "7z a -tzip {0} {1}" .format(target, ' '.join(source))
print(zip_command)
#Run the backup
if os.system(zip_command) == 0:
print('Successful backup', target)
else:
print('Backup FAILED')
source = ['"D:\\Warlock"', 'C:\\Druid' is missing an end bracket. Should be source = ['"D:\\Warlock"', 'C:\\Druid'].
Edit: Also,
zip_commnad = "7z a -tzip {0} {1}" .format(target, ' '.join(source))
print(zip_command)
should be
zip_command = "7z a -tzip {0} {1}" .format(target, ' '.join(source))
print(zip_command)
i.e., spell command correctly and fix the indentation. Additionally, although defining the backup paths like you are is not an error, I'd agree with abaumg's comment that using raw strings would be a lot clearer.
In Python, an invalid syntax error often means that there is a syntax error, one or more lines above the line number that is reported.
Use an editor that does parenthesis hightlighting so that you can move your cursor along the line and see where there are missing or too many parentheses, braces, brackets, etc.
Also, you might want to have a look at the os.path module and get rid of the C: and the \ from your filenames. It is possible to make Python code portable between Linux and Windows. The drivenames could come from options (sys.argv) or a config file (ConfigParser) and the \ can be replaced by a single / and then you can use os.path.normcase() to normalize it for the current OS.
I'm working on a bit of code that is supposed to run an exe file inside a folder on my system and getting an error saying...
WindowsError: [Error 3] The system cannot find the path specified.
Here's a bit of the code:
exepath = os.path.join(EXE file localtion)
exepath = '"' + os.path.normpath(exepath) + '"'
cmd = [exepath, '-el', str(el), '-n', str(z)]
print 'The python program is running this command:'
print cmd
process = Popen(cmd, stderr=STDOUT, stdout=PIPE)
outputstring = process.communicate()[0]
I have imported subprocess and also from subprocess import *
For example, This is how my exe file location looks like in the first line of the code I show:
exepath= os.path.join('/Program Files','next folder','next folder','blah.exe')
Am I missing something?
You need to properly escape the space in the executable path
Besides properly escaping spaces and other characters that could cause problems (such as /), you can also use the 8 character old DOS paths.
For example, Program Files would be:
Progra~1 , making sure to append ~1 for the last two characters.
EDIT: You could add an r to the front of the string, making it a raw literal. Python would read the string character for character. Like this:
r " \Program files"
If I remember correctly, you don't need to quote your executuable file path, like you do in the second line.
EDIT: Well, just grabbed nearby Windows box and tested this. Popen works the same regardless the path is quoted or not. So this is not an issue.
AFAIK, there is no need to surround the path in quotation marks unless cmd.exe is involved in running the program.
In addition, you might want to use the environment variable ProgramFiles to find out the actual location of 'Program Files' because that depends on regional settings and can also be tweaked using TweakUI.