Python - how to add initial MP3 attributes - python

I used to get songs with the artist and the song name in the file name (for example - "britney spears - oops i did it again".
My script have 2 purposes:
1.add the artist name and song to his MP3's attributes (Using eyed3).
2.create a new folder to the artist in my main music folder (if I already don't have one).
My problem is that if the MP3 file have no attributes, I can't add it new ones..
Here is my code (It's my first one :-))..Thanks!
#That's the 0.2 ver of my code
import os
import shutil
import eyed3.id3
songs_path = raw_input("Please insert the path of your Songs: ")
music_path = raw_input("Please insert the path of your music folders location: ")
#That's function supposed to present the files in a path
def files_in_folder(m):
Files = os.listdir(m)
return Files
mp3_files_list = files_in_folder(downloads_path)
artist_list = files_in_folder(music_path)
for i in mp3_files_list:
song_artist, song_title = i.split(' - ')
if not os.path.exists(music_path + '\\' + song_artist):
os.mkdir(music_path + '\\' + song_artist, 0777 )
src_file = os.path.join(downloads_path, i)
dst_file = os.path.join(music_path + '\\' + song_artist + '\\' + song_title)
print src_file
print dst_file
shutil.move(src_file, dst_file)
track_mp3_file = eyed3.load(dst_file)
if track_mp3_file.tag is None:
track_mp3_file.tag = eyed3.id3.Tag()
track_mp3_file.tag.file_info = eyed3.id3.FileInfo(dst_file)
track_mp3_file.tag.artist = unicode(song_artist, "UTF-8")
print track_mp3_file.tag.artist
track_mp3_file.tag.title = unicode(song_title, "UTF-8")
track_mp3_file.tag.save()

try to save the tag with another id3 version:
track_mp3_file.tag.save(version=(2, 3, 0))
from wikipedia:
Windows Explorer and Windows Media Player cannot handle ID3v2.4 tags
in any version, up to and including Windows 8 / Windows Media Player
12. Windows can understand ID3v2 up to and including version 2.3

Related

Need help to make mail merge fully automated with python and without MS office installed

I am doing mail merge using docxtpl but to make it fully automated I have to make the context dynamic so I don't have to make change in code everytime for the different templates.
Here is the code:
import pandas as pd
import os
from docxtpl import DocxTemplate
#Enter the complete filepath to the Word Template
#template_path = input("Insert the template file path : ")
template_path = os.getcwd() + "/sampledoc.docx"
print("Reading template from: " + template_path)
#For print variables
tpl = DocxTemplate(template_path)
variables = tpl.get_undeclared_template_variables()
print(f"\n Reading variables\n{variables}")
#Enter the complete filepath to the excel file which has the data
#source_path = input("Insert the source data file path : ")
source_path = os.getcwd() + "/source_data.xlsx"
print("\nReading source data from: " + source_path)
df = pd.read_excel(source_path)
print(f"\nPrinting source data\n{df}")
#Enter the complete filepath to the excel file where exported files will be saved
#save_dir = input("InserInsert the export directory path : ")
#os.chdir("export")
save_dir = "/storage/emulated/0/python/export/"
for variable in variables:
locals()[variable] = df[variable].values
zipped = zip(Name,Age,Roll,Class,Score)
print("\nPerforming Mail Merge !")
for a,b,c,d,e in zipped:
context = {"Name":a,"Age":b,"Roll":c,"Class":d,"Score":e}
tpl.render(context)
tpl.save(save_dir + '{}.docx'.format(a))
print("\nCongratulation! All files are exported to:\n"
+ str(save_dir[:-1]))
Want to change these bellow line dynamic so I don't have write the field name for different templates.
zipped = zip(Name,Age,Roll,Class,Score
context = {"Name":a,"Age":b,"Roll":c,"Class":d,"Score":e}
If anyone need the code by help of #furas
The code is:
for index, row in df[variables].iterrows():
context = row.to_dict()
tpl.render(context)
tpl.save(save_dir + '{}.docx'.format(context["Name"]))
The full code is also given bellow:
import pandas as pd
import os
from docxtpl import DocxTemplate
#Enter the complete filepath to the Word Template
#template_path = input("Insert the Word template file path : ")
template_path = os.getcwd() + "/sampledoc.docx"
print("\nReading template from: " + template_path)
#To print variables
tpl = DocxTemplate(template_path)
variables = list(tpl.get_undeclared_template_variables())
print(f"\nReading variables\n{variables}")
#Enter the complete filepath of the excel file which has the data
#source_path = input("Insert the source Excel data file path : ")
source_path = os.getcwd() + "/source_data.xlsx"
print("\nReading source data from: " + source_path)
df = pd.read_excel(source_path)
print(f"\nPrinting source data\n{df}")
#Enter the complete directory path where exported files to be saved
#save_dir = input("Insert the export directory path : ")
#save_dir = "/storage/emulated/0/python/export/"
os.chdir("export")
save_dir = os.getcwd() + "/"
for index, row in df[variables].iterrows():
context = row.to_dict()
tpl.render(context)
tpl.save(save_dir + '{}.docx'.format(context["Name"]))
print("\nCongratulation! All files are exported to:\n" + save_dir)

Python Tkinter should use default directory, if I don't specify the directory

I have the following program: https://i.stack.imgur.com/TgzXz.png. Now if I press the Download Location Button, then it should download the song to the chosen directory, this works perfectly. But if I don't press the button, then it should use a directory, which I chose, "a default directory" and move the file to this "default directory"
Code of the "Choose Download Location Button"
def select_download_location():
global destination_source_new
destination_source_new =
filedialog.askdirectory(initialdir=os.path.normpath(r'C:\Users\kevin\Music'))
Code of the moving file to download location:
filename_url = "y2meta.com"
format = ".mp3"
space = filename_url + " "
hyphen ="- "
quality_file_320 = " (320 kbps)"
backslash = "\\"
filename = '\\'+ space + hyphen +title+ quality_file_320 +format
# Location where the file is downloaded to
download_source = r'C:\Users\kevin\Downloads'
source = download_source + filename
# Location where the file should be moved to
destination = destination_source_new
# Move the file from the download folder to the destination folder
dest = shutil.move(source,destination)
you can assign destination as below and if destination doesn't changes it will take default destination.
destination_source_new = ''
filename_url = "y2meta.com"
format = ".mp3"
space = filename_url + " "
hyphen = "- "
quality_file_320 = " (320 kbps)"
backslash = "\\"
filename = '\\' + space + hyphen + title + quality_file_320 + format
# Location where the file is downloaded to
download_source = r'C:\Users\kevin\Downloads'
source = download_source + filename
# Location where the file should be moved to
target = r'C:\Users\kevin\Music'
destination = destination_source_new if destination_source_new != '' else target
# Move the file from the download folder to the destination folder
print(source)
print(destination)
dest = shutil.move(source, destination)
Output:
source= C:\Users\kevin\Downloads\y2meta.com - title (320 kbps).mp3
destination= C:\Users\kevin\Music

Looping through folders and comparing files using win32

Looking to use win32 to compare multiple word docs. The naming convention is the same except the modified doc has test.docx added to the file name. The below is the code i have but it is coming up with "pywintypes.com_error: (-2147023170, 'The remote procedure call failed.', None, None)". Any ideas on how i can get this to work? I have around 200docs to compare so python seems to be the way to do it.
import win32com.client
from docx import Document
import os
def get_docx_list(dir_path):
'''
:param dir_path:
:return: List of docx files in the current directory
'''
file_list = []
for path,dir,files in os.walk(dir_path):
for file in files:
if file.endswith("docx") == True and str(file[0]) != "~": #Locate the docx document and exclude temporary files
file_root = path+"\\"+file
file_list.append(file_root)
print("The directory found a total of {0} related files!".format(len(file_list)))
return file_list
def main():
modified_path = r"C:\...\Replaced\SWI\\"
original_path = r"C:\...\Replaced\SWI original\\"
for i, file in enumerate(get_docx_list(modified_path), start=1):
print(f"{i}、Files in progress:{file}")
for i, files in enumerate(get_docx_list(original_path), start=1):
Application = win32com.client.gencache.EnsureDispatch("Word.Application")
Application.CompareDocuments(
Application.Documents.Open(modified_path + file),
Application.Documents.Open(str(original_path) + files))
Application.ActiveDocument.SaveAs(FileName=modified_path + files + "Comparison.docx")
Application.Quit()
if __name__ == '__main__':
main()
For anyone chasing the solution to do bulk word comparisons below is the code I successfully ran through a few hundred docs. Delete the print statements once you have the naming convention sorted.
import win32com.client
import os
def main():
#path directories
modified_path = r"C:\Users\Admin\Desktop\Replaced\SOP- Plant and Equipment\\"
original_path = r"C:\Users\Admin\Desktop\Replaced\SOP - Plant and Equipment Original\\"
save_path = r"C:\Users\Admin\Desktop\Replaced\TEST\\"
file_list1 = os.listdir(r"C:\Users\Admin\Desktop\Replaced\SOP- Plant and Equipment\\")
file_list2 = os.listdir(r"C:\Users\Admin\Desktop\Replaced\SOP - Plant and Equipment Original\\")
#text counter
Number = 0
#loop through files and compare
for file in file_list1:
for files in file_list2:
#if files match do comparision, naming convention to be changed
if files[:-5] + " test.docx" == file:
Number += 1
print(f"The program has completed {Number} of a total of {len(file_list1)} related files!")
try:
Application = win32com.client.gencache.EnsureDispatch("Word.Application")
Application.CompareDocuments(
Application.Documents.Open(modified_path + file),
Application.Documents.Open(str(original_path) + files))
Application.ActiveDocument.ActiveWindow.View.Type = 3
Application.ActiveDocument.SaveAs(FileName=save_path + files[:-5] + " Comparison.docx")
except:
Application.Quit()
pass
if __name__ == '__main__':
main()

Executing Python Script in Terminal When Outside of Script's Directory

I have a Python script that prompts for text input, searches an online Korean dictionary, and then downloads MP3 audio files for the words found. I use the script to help me make Anki flashcards with audio. The script is originally from this post on reddit.
I can execute the script from the terminal while in the directory that the script is stored in. However, when I am in a different directory and execute the script by calling its full path, the script appears to run but does not find any words or download any MP3s. I cannot figure out why the script fails to execute correctly when I call it from a different directory.
The script is stored in the downloads folder on my Mac /Users/matt/Downloads
So, when I run the following commands, it works:
cd Downloads
python3 naver.py
However, when I run the following, the script executes, but doesn't download any MP3s:
python3 /Users/matt/Downloads/naver.py
The full Python script is here:
import urllib.request, json, codecs, math, time
def searchWords(koreanWords):
url = ('https://ko.dict.naver.com/api3/koko/search?' + urllib.parse.urlencode({'query': koreanWords}) + '&range=word&page=1')
response = urllib.request.urlopen(url)
reader = codecs.getreader("utf-8")
jsonInfo = json.load(reader(response))
pageCount = jsonInfo["pagerInfo"]["totalPages"]
searchData = jsonInfo["searchResultMap"]["searchResultListMap"]["WORD"]["items"]
for pageCountInc in range(0, pageCount):
if pageCountInc != 0:
url = ('https://ko.dict.naver.com/api3/koko/search?' + urllib.parse.urlencode({'query': koreanWords}) + '&range=word&page=' + str(pageCountInc+1))
response = urllib.request.urlopen(url)
reader = codecs.getreader("utf-8")
jsonInfo = json.load(reader(response))
searchData = jsonInfo["searchResultMap"]["searchResultListMap"]["WORD"]["items"]
for z in range (0, len(searchData)):
if searchData[z]["handleEntry"] in unchangedWordList:
if searchData[z]["searchPhoneticSymbolList"]:
if searchData[z]["searchPhoneticSymbolList"][0]["phoneticSymbolPath"] != "":
timesDownloaded[unchangedWordList.index(searchData[z]["handleEntry"])] += 1
mp3Link = searchData[z]["searchPhoneticSymbolList"][0]["phoneticSymbolPath"]
if mp3Link not in mp3Links:
mp3Links.append(mp3Link)
urllib.request.urlretrieve(mp3Link, searchData[z]["handleEntry"] + str(timesDownloaded[unchangedWordList.index(searchData[z]["handleEntry"])]) + ".mp3")
time.sleep(.3)
def parseWords(listOfWords):
for x in range(0, math.floor(len(listOfWords)/10)):
tempWords = []
for y in range(0, 10):
tempWords.append(listOfWords[x*10+y])
print("Searching: " + str(x+1) + "/" + str(math.ceil(len(listOfWords)/10)))
searchWords(tempWords)
tempWords = []
for y in range(math.floor(len(listOfWords)/10)*10+1, len(listOfWords)):
tempWords.append(listOfWords[y])
print("Searching: " + str((math.ceil(len(listOfWords)/10))) + "/" + str(math.ceil(len(listOfWords)/10)))
searchWords(tempWords)
unfoundWords = []
unchangedWordList = []
timesDownloaded = []
mp3Links = []
wordInputs = unchangedWordList = input('Enter Words: ').split()
timesDownloaded = [0] * len(unchangedWordList)
parseWords(wordInputs)
for z in range(0, len(timesDownloaded)):
if(timesDownloaded[z] == 0):
unfoundWords.append(unchangedWordList[z])
if unfoundWords:
print(",".join(str(x) for x in unfoundWords) + " could not be found.")
print("Rerunning individual searches for unfound words.")
print(unfoundWords)
oldUnfoundWords = unfoundWords
unfoundWords = []
for x in range(0, len(oldUnfoundWords)):
print("Searching: " + str(x+1) + "/" + str(len(oldUnfoundWords)))
searchWords(oldUnfoundWords[x])
for z in range(0, len(timesDownloaded)):
if(timesDownloaded[z] == 0):
unfoundWords.append(unchangedWordList[z])
if unfoundWords:
print(",".join(str(x) for x in unfoundWords) + " could not be found.")
To answer question of how to save to a specific folder use pathlib to construct the path to MP3 folder.
import os
from pathlib import Path
# Create parent folder
mp3DIR = os.path.join(Path.home(),'Music')
basename = searchData[z]["handleEntry"]
+ str(timesDownloaded[unchangedWordList.index(searchData[z]["handleEntry"])]) + ".mp3"
urllib.request.urlretrieve(mp3Link, os.path.join(mp3Dir, basename))
The reason is the following:
Your python file runs in your current directory. So, when you run this: python3 /Users/matt/Downloads/naver.py, it either runs and saves the mp3 files in the current directory, or it doesn't save anything at all if it doesn't have the permissions to.

trying to store a file in a string python

This is one of my first python projects, and i'm trying to make a script that would write a script which can re-create the src/ directory. this would be what i distribute to users. It uses walk, and writes a python file that first creates all the directories, and then writes the files. The issue i have is making the the files into a single string that i can write to a file.
This is the program i have:
import os
import pickle
src = os.path.dirname(os.path.realpath(__file__)) + os.sep + 'src'
fPack = 'import os \nimport pickle \nmyDir = os.path.dirname(os.path.realpath(__file__))'
Pack =''
print 'Packing ' + src
pickle
for root, dirs, files in os.walk(src, topdown=True):
for name in files:
print os.path.join(root, name)
f = open(os.path.join(root, name), 'r')
Pack = Pack + '\nf = open(os.path.join(myDir,\'' + name + '\'), \'w\')'
fileCont = pickle.dumps(f.read())
Pack = Pack + '\nf.write(pickle.loads(\'' + fileCont + '\'))'
for name in dirs:
print os.path.join(root, name)
fPack = fPack + '\nos.makedirs(os.path.join(myDir,\'' + name + '\'))'
print '==================================================\n\n\n'
print fPack + Pack
f = open(os.getcwd() + os.sep + 'dist' + os.sep + 'Pack.py', 'w')
f.write(fPack)
f.write(Pack)
And if i run it in a directory with on subdirectory, and on file inside it creates this file
import os
import pickle
myDir = os.path.dirname(os.path.realpath(__file__))
os.makedirs(os.path.join(myDir,'SphereText'))
f = open(os.path.join(myDir,'TextMain.py'), 'w')
f.write(pickle.loads('S"########################################################\n#Main SphereText file. #\n#SpereText is a simple Notepad-Like plain text editor #\n########################################################\n\nfrom Tkinter import *\nfrom tkFileDialog import *\nimport tkSimpleDialog\n\nroot = Tk()\nroot.title('SphereText')\n\ndef fSave():\n fileName = asksaveasfilename(parent=root)\n f = open(fileName, 'w')\n f.write(text.get(1.0,END))\n\ndef fOpen():\n fileName = ''\n fileName = askopenfilename(parent=root)\n f = open(fileName, 'r')\n text.delete(1.0,END)\n text.insert(1.0, f.read())\n\ndef tReplace():\n Old = tkSimpleDialog.askstring('SphereText', 'Replace:')\n print Old\n New = tkSimpleDialog.askstring('SphereText', 'With:')\n print New\n content = text.get(1.0,END)\n content = content.replace(Old, New)\n text.delete(1.0,END)\n text.insert(1.0, content)\n \nmenubar = Menu(root)\nmenubar.add_command(label='Save', command=fSave)\nmenubar.add_command(label='Open', command=fOpen)\nmenubar.add_command(label='Replace', command=tReplace)\nroot.config(menu=menubar)\n\ntext = Text(root, wrap=WORD)\n\ntext.pack()\n\nroot.mainloop()\n"
p0
.'))
The 's aren't escaped, and there are two line breaks at the end. i thought that the whole point of serializing was that you could always read it back the same way. Anyone know how i can mak the file a valid string?
Sorry about the newbish question, i just found out i had been trying to reinvent the wheel. apparently, that already exists under the name Squeeze.

Categories

Resources