I am fairly new to Python, teaching it to myself by watching tutorials and doing the trial and error kind of thing, and I ran into a task, which I am not able to solve right now:
I am reading from a file with following code:
def read_file(file):
try:
with open(file) as f:
content = f.read()
return content
except FileNotFoundError:
print("\nThis file does not exist!")
exit()
The file(.txt) I am reading contains a text with multiple placeholders:
Hello {name}, you are on {street_name}!
Now I want to replace the placeholders {name} and {street_name} with their corresponding variables.
I know how f-strings work. Can this somehow be applied to this problem too, or do I have to parse the text to find the placeholders and somehow find out the fitting variable that way?
Each text I read, contains different placeholders. So I have to find out, which placeholder it is and replace it with the according string.
Not sure if that is what you are looking for:
string = "Hello {name}, you are on {street_name}!"
string = string.format(name="Joe", street_name="Main Street")
print(string)
or
string = "Hello {name}, you are on {street_name}!"
name = "Joe"
street_name = "Main Street"
string = string.format(name=name, street_name=street_name)
print(string)
gives you
Hello Joe, you are on Main Street!
See here.
If you actually don't know what placeholders are in the text then you could do something like:
import re
string = "Hello {name}, you are on {street_name}!"
name = "Joe"
street_name = "Main Street"
placeholders = set(re.findall(r"{(\w+)}", string))
string = string.format_map({
placeholder: globals().get(placeholder, "UNKOWN")
for placeholder in placeholders
})
If you know that all placeholders are present as variables, then you could simply do:
string = "Hello {name}, you are on {street_name}!"
name = "Joe"
street_name = "Main Street"
string = string.format_map(globals())
Related
The issue I have is that I'm not able to get the correct part of my txt string. The txt string also has to be in the current order, I can't switch role and name.
txt = \
'''
Company name
leader: Claire
cashier: Ole
'''
def role(name):
start= txt.find(name)-len(name)
end= txt.find('\n', start)
return txt[start:end]
If I type role("Ole") I expect the output to be 'cashier'.
The output I am getting though is 'r: Ole'.
You can create a dictionary that associates the names to the correspondent roles, so that it becomes very easy to retrieve them even in a much longer list:
txt = \
'''
Company name
leader: Claire
cashier: Ole
'''
t = txt.split()
roles = {t[i] : t[i-1].strip(':') for i in range(3, len(t), 2)}
def role(name):
return roles[name]
Once set up, it's pretty intuitive.
stringy = "cashier: Ole"
stringy.partition(':')[0]
you can use .partition and bring only the first element
this will work but if there is anything diff about your string it may break down.
stringy = """ Company name
leader: Claire
cashier: Ole"""
def role(name):
slice = stringy.partition(name)[0]
role_str = slice.split(' ')[-2]
return role_str
The votes are in… and it's up to you to make sure the correct winner is announced!
You've been given a CSV file called nominees.csv, which contains the names of various movies nominated for a prize, and the people who should be announced as the recipient. The file will look like this:
title,director(s)
Schindler's List,Steven Spielberg
"O Brother, Where Art Thou?","Joel Coen, Ethan Coen"
2001: A Space Odyssey,Stanley Kubrick
"Sherlock, Jr.","Buster Keaton, Roscoe Arbuckle"
You should write a program that reads in nominees.csv, asks for the name of the winning title, and prints out specific congratulations. For example, with the above file, your program should work like this:
Winning title: O Brother, Where Art Thou?
Congratulations: Joel Coen, Ethan Coen
Here is another example, using the same file:
Winning title: Schindler's List
Congratulations: Steven Spielberg
Already tried submitting and altering values but line number 10 always gives value error and so does line number 15. When a list of new nominees is applied, it gives the error and fails my code.
def main():
film_director=[]
with open('nominees.csv','r') as read_file:
lines=read_file.readlines()
lines=lines[1:]
for line in lines:
if '"' in line:
if line[0]=='"':
index_second_quotes=line.index('"',1)
index_third_quotes=line.index('"',index_second_quotes+1)
title = line[:index_second_quotes].strip('\"')
directors=line[index_third_quotes:-1].strip('\"').strip()
else:
index_first_quotes = line.index('"')
index_second_quotes = line.index('"', index_first_quotes+1)
title = line[:index_first_quotes-1].strip('\"')
directors = line[index_first_quotes+1:-1].strip('\"').strip()
film_director.append([title,directors])
else:
tokens = line.split(',')
film_director.append([tokens[0].strip(),tokens[1].strip()])
title = input('Winning title: ')
for row in film_director:
if title.strip()==row[0]:
print('Congratulations:',row[1])
break
main()
The error message given is:
Testing a new nominees file. Your submission raised an exception of type ValueError. This occurred on line 10 of program.py.
The above number of condition checks, splitting, concatenation can be omitted with regular expression. You can make use of the below code with a single regular expression and a split
import re
with open("nominees.csv") as cf:
lines = cf.readlines()
for line in lines[1:]:
reg_match = re.match(r'"([^""]*)","([^""]*)"$', line)
if reg_match:
win_title, director = reg_match.group(1), reg_match.group(2)
else:
win_title, director = line.split(",")
print("Winning title: %s" % win_title)
print("Congratulations: %s" % director.strip())
I am trying to make a program that will create a LaTex file (.tex) with a preamble in it, and sooner some sections. I have defined my function thepreamble(title,subject) such that the inputs will be created in the string, which is seen below in my code.
# -*- coding: utf-8 -*-
import io
def thepreamble(title, subject):
global preamble
preamble = r'''\documentclass[a4paper, 12pt]{extarticle}
\usepackage[T1]{fontenc}
\usepackage[utf8x]{inputenc}
\usepackage[english, danish]{babel}
\usepackage{fancyhdr}
\usepackage[dvipsnames]{xcolor}
\usepackage{mathtools}
\usepackage{graphicx}
\usepackage{amssymb}
\usepackage{titlesec}
\usepackage[left=0.5in, right=0.5in, top=0.8in, bottom=0.8in]{geometry}
\usepackage{lipsum}
\usepackage[breaklinks, colorlinks=true,linkcolor=NavyBlue, citecolor=blue, urlcolor=Blue, linktoc=all]{hyperref}
\usepackage[utf8x]{inputenc}
\usepackage{titlesec}
\usepackage{fix-cm}
\usepackage{titletoc}
\usepackage{tocloft}
\usepackage{setspace}
\usepackage[all]{hypcap}
\usepackage{tikz, pgfplots}
\usetikzlibrary{calc}
\usepackage{tkz-euclide}
\usetkzobj{all}
\usetikzlibrary{positioning}
\usepackage{tikzrput}
\usetikzlibrary{arrows.meta}
\usepackage[labelfont=bf]{caption}
\usepackage[hang, flushmargin]{footmisc}
\usepackage{footnotebackref}
\pagestyle{fancy}
\fancyhf{}
\fancyfoot[R]{\textbf \thepage}
\renewcommand{\headrulewidth}{0pt}
\renewcommand{\footrulewidth}{2pt}
\renewcommand{\footrule}{\hbox to\headwidth{\color{NavyBlue}\leaders\hrule height \footrulewidth\hfill}}
\newcommand{\dl}[1]{\underline{\underline{#1}}}
\setcounter{tocdepth}{2}
\setcounter{secnumdepth}{0}
\begin{document}
\begin{titlepage}
\begin{center}
\vspace*{30ex}
{\fontsize{38}{0}\selectfont \bfseries \fontfamily{put}\selectfont \color{NavyBlue} '''+ str(title)+'''} \\
[3ex]
{\fontsize{18}{0}\selectfont \bfseries \fontfamily{put}\selectfont \color{NavyBlue} ('''+str(subject)+ ''')}\\
[14ex]
{ \fontsize{15}{0}\selectfont Casper Juul Lorentzen} \\
[3ex]
{\large \scshape 1.z} \\
[2ex]
{\large \scshape 2018}\\
\vspace{\fill}
\includegraphics[scale=0.45]{C:/LaTeX/Next.png} \\
[4mm]
\small{\bfseries Albertslund Gymnasium \& HF} \\
\end{center}
\end{titlepage}
\renewcommand\contentsname{Indhold \vspace{3ex}}
\tableofcontents
\thispagestyle{empty}
\newpage
\setcounter{page}{1}
'''
return preamble
def sections(numsec, numsubsec):
numbers = []
numbers.extend(numsubsec)
global tasks
tasks = []
print("")
#Brug præfikset 'r' foran unicodes
print("")
for n,i in zip(range(1, numsec+1),range(0,numsec)):
print("")
opgaver = "\section{Opgave "+str(n)+"}"
print(opgaver)
print("")
tasks.append(opgaver)
for x in range(int(numsubsec[i])):
print("\subsection{}")
print("")
return tasks
def runprogram():
encoding ='utf8'
titlefile = input("Title (file): ")
title = input("Title of document: ")
subject = input("Subject: ")
numsec = int(input("How many sections? "))
filename = "C:\\Users\\Casper\\Documents\\LaTeX\\fire.tex"
while True:
numsubsec = input("How many subsections?")
while len(numsubsec) !=numsec:
print("")
numsubsec =input("Error; input must be of "+ str(numsec) + " digits ")
try:
with io.open(filename.replace('fire.tex',titlefile+".tex"), 'w', encoding=encoding) as f:
f.write(unicode_thepreamble(title, subject))
f.close()
#sections(numsec, numsubsec)
break
except:
print("Error")
runprogram()
Whenever I run the program, it creates a new .tex file with the name of
titlefile = input("Title (file): ")
As you can see, i have defined preamble as a text with unicode characters in it. And when I run the program, it writes almost everything of the preamble string in the tex document, but it cuts some of it off and creates weird symbol, like this:
tex document created
I named the title 'stackoverflow' and the subject 'python problem', and that works fine. But what ought to be '\renewcommand' is in the document ' enewcommand'. I do not know how to fix this. I just want precisely what my preamble strings says.
When you merge your title and subject into the string you have to make the second piece raw again
r''' bla bla '''+ str(title) + r''' bla bla'''
The second "r" is missing, twice in your example.
You should consider merging using str.format().
I try to split a String from a database (SQLite). The String has a linebreak \n and I want split it there in 2 parts. It works with a normal String for example text = "Hello \n World". But if I use the string from my database it doesn't work (the text is saved correctly with \n in the database!!)
My Code for getting the first part of the string:
from django import template
from products.models import News
register = template.Library()
#register.simple_tag
def get_first_title(id):
search_value = "\n"
news = News.objects.values('title')
title = news.filter(pk=id)
number = str(title).find(search_value)
first_title = str(title)[0:number]
return first_title
Try this:
#register.simple_tag
def get_first_title(id):
news = News.objects.get(pk=id)
return news.title.split("\n")[0]
Although you should probably catch posible exceptions with:
#register.simple_tag
def get_first_title(id):
try:
news = News.objects.get(pk=id)
splitted_title = news.title.split("\n")
if splitted_title:
return splitted_title[0]
except News.DoesNotExist:
# raise exception or return None or something
Use the following code instead of your code in the last 4 lines
title = news.filter(pk=id)
number = str(title).split(" ")
# number is a list of strings
print(number , len(number))
I am relatively new to programming, and I have a small problem writing a python equivalent of Snip for spotify for ubuntu(linux)
Somehow i can encode the title correctly, but am unable to encode the artist the same way
when i try to encode the artist in the same fashion i get this:
File "./songfinder.py", line 11, in currentplaying
artiststr = str((metadata['xesam:artist']).encode('utf-8'))
AttributeError: 'dbus.Array' object has no attribute 'encode'
however the title is done exactly the same and that is working.
Code so far IS working but has for example \xd8 instead of Ø, and similar:
import dbus
session_bus = dbus.SessionBus()
spotify_bus = session_bus.get_object("org.mpris.MediaPlayer2.spotify", "/org/mpris/MediaPlayer2")
spotify_properties = dbus.Interface(spotify_bus, "org.freedesktop.DBus.Properties")
def currentplaying():
metadata = spotify_properties.Get("org.mpris.MediaPlayer2.Player", "Metadata")
title = str((metadata['xesam:title']).encode('utf-8'))
artiststr = str((metadata['xesam:artist']))
if ("dbus.string" in artiststr.lower()):
artists = artiststr.split("(u")
artist = artists[1]
artists = artist.split(")],")
artist = artists[0]
artist = artist.replace("(u", "")
else:
artist = "'unknown'"
artist = (artist.replace("'",""))
playing = (artist + " - " + title + " ")
return playing
#save playing to file.txt
relevant qna's:
Replace non-ascii chars from a unicode string in Python
Why it does not resolve my problem: I would like to print/save the actual character, not replace it with similar ones
Looking at your question metadata contains at least something like this with Unicode strings. The artist field seems to be some sort of iterable the begins with the artist. Something like this (feel free to post actual metadata content):
metadata = {'xesam:title':u'title','xesam:artist':[u'artist']}
In the title assignment line, str is unnecessary since encoding a Unicode string returns a str anyway, but no need to encode it either. Unicode strings represent text, so leave it that way:
title = metadata['xesam:title']
Similar for artist assignment, but get the first element of the iterable:
artist = metadata['xesam:artist'][0]
Next, in your song-updating logic, use io.open to open the files with a UTF-8 encoding. This lets Unicode strings (text) be written directly and the file will handle the encoding. Also use a with statement to automatically close the file when the with ends.
Program with recommended changes:
import time
import dbus
import io
session_bus = dbus.SessionBus()
spotify_bus = session_bus.get_object("org.mpris.MediaPlayer2.spotify", "/org/mpris/MediaPlayer2")
spotify_properties = dbus.Interface(spotify_bus, "org.freedesktop.DBus.Properties")
def currentplaying():
metadata = spotify_properties.Get("org.mpris.MediaPlayer2.Player", "Metadata")
title = metadata['xesam:title']
artist = metadata['xesam:artist'][0]
playing = artist + " - " + title + " "
return playing
while True:
with io.open('currentsongspotify.txt', encoding='utf8') as filetxt:
oldtitle = filetxt.read()
newtitle = currentplaying()
if newtitle == oldtitle:
time.sleep(1)
else:
with io.open('currentsongspotify.txt','w',encoding='utf8') as filetxt: # save newtitle to file, overwriting existing data
filetxt.write(newtitle)
print 'new file saved:',newtitle
The error you getting is not about unicode, it is about wrong type. Python complains that you trying to call string method encode from the array object. Which does not have this method.
The first this I would try is to remove redundant brackets here it getting artiststr like this: artiststr = str(metadata['xesam:artist']).
But I'm not sure this would work. If it doesn't work, you need to find out what type has metadata['xesam:artist']. Looks like it is not string, but array. So you need to fix the code which fills metadata['xesam:artist'] with data. You can try to use debugger or just print() function to find out the content of metadata['xesam:artist']. Or provide the relevant code in you question too.
Final program, feel free to use if you like:
import time
import dbus
session_bus = dbus.SessionBus()
spotify_bus = session_bus.get_object("org.mpris.MediaPlayer2.spotify", "/org/mpris/MediaPlayer2")
spotify_properties = dbus.Interface(spotify_bus, "org.freedesktop.DBus.Properties")
def currentplaying():
metadata = spotify_properties.Get("org.mpris.MediaPlayer2.Player", "Metadata")
title = str((metadata['xesam:title']).encode('utf-8'))
artiststr = str((metadata['xesam:artist'])[0].encode('utf-8'))
artist = artiststr
playing = (artist + " - " + title + " ")
return playing
while True:
filetxt = open("/home/USER/Desktop/currentsongspotify.txt", "r")
oldtitle = filetxt.read()
filetxt.close()
newtitle = str(currentplaying())
if(newtitle == oldtitle):
time.sleep(1)
else:
filetxt = open("/home/USER/Desktop/currentsongspotify.txt", "w") #save newtitle to file, overwriting existing data
filetxt.write(str(newtitle))
print("new file saved: " + newtitle)