Python gTTS several mp3 files issue - python

I am creating an app based on speech. Everything works fine but I do not want my app to use outside program to open mp3 file. At the moment program can do several commands only if I will use: cmd
def speak(text):
tts = gTTS(text=text, lang='pl')
filename = 'speak.mp3'
tts.save(filename)
cmd = filename #works for several commands with external program
os.system(cmd)
What I would like to do is something like this:
def speak(text):
tts = gTTS(text=text, lang='pl')
filename = 'speak.mp3'
tts.save(filename)
playsound.playsound(filename)
return speak
Unfortunately it works only for first audio input, second one gives error:
File "C:\Users\Admin\AppData\Local\Programs\Python\Python38-32\lib\site-packages\gtts\tts.py", line 294, in save
with open(str(savefile), 'wb') as f:
PermissionError: [Errno 13] Permission denied: 'speak.mp3'
I was trying to delete mp3 file after it has been saved and played but it did not helped.
Any idea how to solve it?

Try to see the permissions of the file that has been created. It might have only read permissions.

When passing in the function, attempt to supply various file names for each of the distinct texts, or use the random.randit() method to set different file names, or use the current time as your file name using the time module.

Related

configparser NoSectionError Python

I have made a config file named "config.cfg" that's on the same folder of my .py file.
My config file is like this:
[NetAccess]
host=localhost
port=3306
[Credentials]
username=myuser
password=mypass
[Database]
name=mydb
in my .py file I have this code:
import configparser
config = configparser.ConfigParser()
config.read('config.cfg')
__DBMSuser = config.get('Credentials', 'username')
__DBMSpsw = config.get('Credentials', 'password')
When I launch my program, I receive this error:
configparser.NoSectionError: No section: 'Credentials'
Can someone help me?
I've solved it. My code was correct, and the .cfg file was correctly saved in the folder of my program, but because of other parts of my code, my current directory changed to "C:/Windows/Service32". Not reading the file, I had not error until I was trying to read the sections, so I got NoSectionError.
To solve it, I've choice a standard folder (in AppData) where to save my file and read it and then I've used the absolute path.
Your code is working for me. Most likely the issue is reading the config file itself. Config Parser's read method is configured to fail silently if it fails to find or read the file, but the read function returns a read_ok boolean flag. Use it to check if the read was successful:
import configparser
config = configparser.ConfigParser()
filename = 'config.cfg'
read_ok = config.read(filename)
if read_ok:
__DBMSuser = config['Credentials']['username']
__DBMSpsw = config['Credentials']['password']
else:
print(f'Could not read file {filename}')
There is no mistake in your code, cuz it works for me.
I think there is some small error with file:
Make sure your file is in same directory as python file
Have you saved your file? maybe you forgot to press ctrl+s
If even that's not working for you, try another version of Python

I keep getting a permission denial error whenever I try to access a file in a speech recognition program

I'm trying out speech recognition and using it as input for some statements while having the program "speak" back to me using the playsound and gTTS modules. But I have ran into an issue that I can't find the solution for, I tried the most common solutions but with no luck.
The program uses the playsound, speech_recognition, and gTTS modules and two functions; speak() lets the program speak back to the user using google's text to sound translation, and get_audio() that receives input from the user's microphone using speech_recognition's recognizer and microphone classes.
import os
import time
import playsound
import speech_recognition as sr
from gtts import gTTS
run = True
def speak(text):
tts = gTTS(text=text, lang="en")
filename = "voice.mp3"
tts.save(filename)
playsound.playsound(filename)
def get_audio():
r = sr.Recognizer()
with sr.Microphone() as source:
audio = r.listen(source)
said = ""
try:
said = r.recognize_google(audio)
print(said)
except Exception as e:
print("Exception: " + str(e))
return said
while run == True:
text = get_audio()
if "hello" in text:
speak("Hello, how are you?")
if "what are you" in text:
print("")
speak("I am a speech recognition program")
if "goodbye" in text:
speak("Talk to you later" or "Bye" or "Cya")
run = False
I have the program set up with a while loop so a conversation can play out, and it only breaks once the user says "Goodbye". The problem seems to be that the .mp3 file (voice.mp3 which is what the speak() function uses to store audio for the program to play back) can't be accessed after its creation. Both the python file and mp3 file are stored within the same folder.
Here is the error message in full:
who are you
hello
Traceback (most recent call last):
File "c:\Users\User\OneDrive\Documents\VS Code Projects\Speech Recognition\main_va.py", line 34, in <module>
speak("Hello, how are you?")
File "c:\Users\User\OneDrive\Documents\VS Code Projects\Speech Recognition\main_va.py", line 12, in speak
tts.save(filename)
File "C:\Python\Python310\lib\site-packages\gtts\tts.py", line 328, in save
with open(str(savefile), "wb") as f:
PermissionError: [Errno 13] Permission denied: 'voice.mp3'
PS C:\Users\User\OneDrive\Documents\VS Code Projects\Speech Recognition>
I received a response on the first call ("who are you"), but then the error message popped up after the second call ("hello").
Specs: python 3.10.4
playsound 1.2.2
Rest is up to date
Your solution works fine.
I just would tweak it to leave the file behind (in case you want to listen to it for testing purposes) and instead, remove it at the beginning if it exists.
Also passing filename to your function ensures nothing is hard coded
def speak(text, filename):
if os.path.exists(filename):
os.remove(filename)
tts = gTTS(text=text, lang="en")
tts.save(filename)
playsound.playsound(filename)
I found a solution that seems to work just fine; I delete the .mp3 file each time after I use it, so at the end of the speak() function I just use os.remove(filename) and then the next time it wants to say something a new file is created.
I found some other solutions saying that you should rename the filename every time you make one, but that would make too much clutter for me.
Here is the change that I made to my code, it was just a single line within the speak() function:
def speak(text):
tts = gTTS(text=text, lang="en")
filename = "voice.mp3"
tts.save(filename)
playsound.playsound(filename)
os.remove("voice.mp3")
This works perfectly for me so far, it can take in as many inputs as needed since the file is deleted and recreated every time the speak() function is used.
Again if a better and more efficient solution is suggested or found, I'll gladly take it.

Why a new NamedTemporaryFile object has a path, but a file is not available? [duplicate]

I am attempting to create and write to a temporary file on Windows OS using Python. I have used the Python module tempfile to create a temporary file.
But when I go to write that temporary file I get an error Permission Denied. Am I not allowed to write to temporary files?! Am I doing something wrong? If I want to create and write to a temporary file how should should I do it in Python? I want to create a temporary file in the temp directory for security purposes and not locally (in the dir the .exe is executing).
IOError: [Errno 13] Permission denied: 'c:\\users\\blah~1\\appdata\\local\\temp\\tmpiwz8qw'
temp = tempfile.NamedTemporaryFile().name
f = open(temp, 'w') # error occurs on this line
NamedTemporaryFile actually creates and opens the file for you, there's no need for you to open it again for writing.
In fact, the Python docs state:
Whether the name can be used to open the file a second time, while the named temporary file is still open, varies across platforms (it can be so used on Unix; it cannot on Windows NT or later).
That's why you're getting your permission error. What you're probably after is something like:
f = tempfile.NamedTemporaryFile(mode='w') # open file
temp = f.name # get name (if needed)
Use the delete parameter as below:
tmpf = NamedTemporaryFile(delete=False)
But then you need to manually delete the temporary file once you are done with it.
tmpf.close()
os.unlink(tmpf.name)
Reference for bug: https://github.com/bravoserver/bravo/issues/111
regards,
Vidyesh
Consider using os.path.join(tempfile.gettempdir(), os.urandom(24).hex()) instead. It's reliable, cross-platform, and the only caveat is that it doesn't work on FAT partitions.
NamedTemporaryFile has a number of issues, not the least of which is that it can fail to create files because of a permission error, fail to detect the permission error, and then loop millions of times, hanging your program and your filesystem.
The following custom implementation of named temporary file is expanded on the original answer by Erik Aronesty:
import os
import tempfile
class CustomNamedTemporaryFile:
"""
This custom implementation is needed because of the following limitation of tempfile.NamedTemporaryFile:
> Whether the name can be used to open the file a second time, while the named temporary file is still open,
> varies across platforms (it can be so used on Unix; it cannot on Windows NT or later).
"""
def __init__(self, mode='wb', delete=True):
self._mode = mode
self._delete = delete
def __enter__(self):
# Generate a random temporary file name
file_name = os.path.join(tempfile.gettempdir(), os.urandom(24).hex())
# Ensure the file is created
open(file_name, "x").close()
# Open the file in the given mode
self._tempFile = open(file_name, self._mode)
return self._tempFile
def __exit__(self, exc_type, exc_val, exc_tb):
self._tempFile.close()
if self._delete:
os.remove(self._tempFile.name)
This issue might be more complex than many of you think. Anyway this was my solution:
Make use of atexit module
def delete_files(files):
for file in files:
file.close()
os.unlink(file.name)
Make NamedTemporaryFile delete=False
temp_files = []
result_file = NamedTemporaryFile(dir=tmp_path(), suffix=".xlsx", delete=False)
self.temp_files.append(result_file)
Register delete_files as a clean up function
atexit.register(delete_files, temp_files)
tempfile.NamedTemporaryFile() :
It creates and opens a temporary file for you.
f = open(temp, 'w') :
You are again going to open the file which is already open and that's why you are getting Permission Denied error.
If you really wants to open the file again then you first need to close it which will look something like this-
temp= tempfile.NamedTemporaryFile()
temp.close()
f = open(temp.name, 'w')
Permission was denied because the file is Open during line 2 of your code.
close it with f.close() first then you can start writing on your tempfile

Python ignores file type when creating file

I'm trying to create a .txt file with some data, and I want the file name to be the current time. But when I run my code it creates an empty file instead, without any file-type. Here is the code in question:
filename = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d_%H:%M')
with open('%s.txt' % filename, 'w') as open_file:
# writing to file
It seems to ignore the ".txt" part because if i write the code like this it works just fine:
with open('filename.txt', 'w') as open_file:
It runs fine on my machine (Ubuntu 16.04 and python 3.5)
import datetime
import time
filename = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d_%H:%M')
with open('%s.txt' % filename, 'w') as file:
file.write('code written')
please provide more info
And yes i am getting .txt in my file name
In windows, you cant use : in the filename. It stops the creation of the file when it reaches the colon.

Close already open csv in Python

Is there a way for Python to close that the file is already open file.
Or at the very least display a popup that file is open or a custom written error message popup for permission error.
As to avoid:
PermissionError: [Errno 13] Permission denied: 'C:\\zf.csv'
I've seen a lot of solutions that open a file then close it through python. But in my case. Lets say I left my csv open and then tried to run the job.
How can I make it so it closes the currently opened csv?
I've tried the below variations but none seem to work as they expect that I have already opened the csv at an earlier point through python. I suspect I'm over complicating this.
f = 'C:\\zf.csv'
file.close()
AttributeError: 'str' object has no attribute 'close'
This gives an error as there is no reference to opening of file but simply strings.
Or even..
theFile = open(f)
file_content = theFile.read()
# do whatever you need to do
theFile.close()
As well as:
fileobj=open('C:\\zf.csv',"wb+")
if not fileobj.closed:
print("file is already opened")
How do I close an already open csv?
The only workaround I can think of would be to add a messagebox, though I can't seem to get it to detect the file.
filename = "C:\\zf.csv"
if not os.access(filename, os.W_OK):
print("Write access not permitted on %s" % filename)
messagebox.showinfo("Title", "Close your CSV")
Try using a with context, which will manage the close (__exit__) operation smoothly at the end of the context:
with open(...) as theFile:
file_content = theFile.read()
You can also try to copy the file to a temporary file, and open/close/remove it at will. It requires that you have read access to the original, though.
In this example I have a file "test.txt" that is write-only (chmod 444) and it throws a "Permission denied" error if I try writing to it directly. I copy it to a temporary file that has "777" rights so that I can do what I want with it:
import tempfile, shutil, os
def create_temporary_copy(path):
temp_dir = tempfile.gettempdir()
temp_path = os.path.join(temp_dir, 'temp_file_name')
os.chmod(temp_path, 0o777); # give full access to the tempfile so we can copy
shutil.copy2(path, temp_path) # copy the original into the temp one
os.chmod(temp_path, 0o777); # replace permissions from the original file
return temp_path
path = "./test.txt" # original file
copy_path = create_temporary_copy(path) # temp copy
with open(copy_path, "w") as g: # can do what I want with it
g.write("TEST\n")
f = open("C:/Users/amol/Downloads/result.csv", "r")
print(f.readlines()) #just to check file is open
f.close()
# here you can add above print statement to check if file is closed or not. I am using python 3.5

Categories