GVKun编程网logo

Formatting Strings with the Python Template Class

23

在这篇文章中,我们将为您详细介绍FormattingStringswiththePythonTemplateClass的内容。此外,我们还会涉及一些关于2019-02-13Python爬虫问题NotI

在这篇文章中,我们将为您详细介绍Formatting Strings with the Python Template Class的内容。此外,我们还会涉及一些关于2019-02-13 Python爬虫问题 NotImplementedError: Only the following pseudo-classes are implemented: nth...、An error happened during template parsing (template: "class path resource [templates/index.h...、An error happened during template parsing (template: "class path resource [templates/user.html]、AttributeError: 'Settings' object has no attribute 'TEMPLATE_CONTEXT_PROCESSORS'的知识,以帮助您更全面地了解这个主题。

本文目录一览:

Formatting Strings with the Python Template Class

Formatting Strings with the Python Template Class

http://stackabuse.com/formatting-strings-with-the-python-template-class/


Introduction

Python Templates are used to substitute data into strings. With Templates, we gain a heavily customizable interface for string substitution (or string interpolation).

Python already offers many ways to substitute strings, including the recently introduced f-Strings. While it is less common to substitute strings with Templates, its power lies in how we can customize our string formatting rules.

In this article, we''ll format strings with Python''s Template class. We''ll then have a look at how we can change the way our Templates can substitute data into strings.

For a better understanding of these topics, you''ll require some basic knowledge on how to work with classes and regular expressions.

Understanding the Python Template Class

The Python Template class was added to the string module since Python 2.4. This class is intended to be used as an alternative to the built-in substitution options (mainly to %) for creating complex string-based templates and for handling them in a user-friendly way.

The class''s implementation uses regular expressions to match a general pattern of valid template strings. A valid template string, or placeholder, consists of two parts:

  • The $ symbol
  • A valid Python identifier. An identifier is any sequence of upper and lower case letters A to Z, underscores (_), and digits 0 to 9. An identifier cannot begin with digits nor can it be a Python keyword.

In a template string, $name and $age would be considered valid placeholders.

To use the Python Template class in our code, we need to:

  1. Import Template from the string module
  2. Create a valid template string
  3. Instantiate Template using the template string as an argument
  4. Perform the substitution using a substitution method

Here''s a basic example of how we can use the Python Template class in our code:

>>> from string import Template
>>> temp_str = ''Hi $name, welcome to $site''
>>> temp_obj = Template(temp_str)
>>> temp_obj.substitute(name=''John Doe'', site=''StackAbuse.com'')
''Hi John Doe, welcome to StackAbuse.com''

We notice that when we build the template string temp_str, we use two placeholders: $name and $site. The $ sign performs the actual substitution and the identifiers (name and site) are used to map the placeholders to the concrete objects that we need to insert into the template string.

The magic is completed when we use the substitute() method to perform the substitution and build the desired string. Think of substitute() as if we were telling Python, go through this string and if you find $name, then replace it for John Doe. Continue searching through the string and, if you find the identifier $site, then turn it into StackAbuse.com.

The names of the arguments that we pass to .substitute() need to match with the identifiers that we used in the placeholders of our template string.

The most important difference between Template and the rest of the string substitution tools available in Python is that the type of the argument is not taken into account. We can pass in any type of object that can be converted into a valid Python string. The Template class will automatically convert these objects into strings and then insert them into the final string.

Now that we know the basics on how to use the Python Template class, let''s dive into the details of its implementation to get a better understanding of how the class works internally. With this knowledge at hand, we''ll be able to effectively use the class in our code.

The Template String

The template string is a regular Python string that includes special placeholders. As we''ve seen before, these placeholders are created using a $ sign, along with a valid Python identifier. Once we have a valid template string, the placeholders can be replaced by our own values to create a more elaborated string.

According to PEP 292 -- Simpler String Substitutions, the following rules apply for the use of the $ sign in placeholders:

  1. $$ is an escape; it is replaced with a single $
  2. $identifier names a substitution placeholder matching a mapping key of "identifier". By default, "identifier" must spell a Python identifier as defined in http://docs.python.org/reference/lexical_analysis.html#identifiers-and-keywords. The first non-identifier character after the $ character terminates this placeholder specification.
  3. ${identifier} is equivalent to $identifier. It is required when valid identifier characters follow the placeholder but are not part of the placeholder, e.g. "${noun}ification". (Source)

Let''s code some examples to better understand how these rules work.

We''ll start with an example of how we can escape the $ sign. Suppose we''re dealing with currencies and we need to have the dollar sign in our resulting strings. We can double the $ sign to escape itself in the template string as follows:

>>> budget = Template(''The $time budget for investment is $$$amount'')
>>> budget.substitute(time=''monthly'', amount=''1,000.00'')
''The monthly budget for investment is $1,000.00''

Note that there is no need to add and extra space between the escaped sign and next placeholder like we did in $$$amount. Templates are smart enough to be able to escape the $ sign correctly.

The second rule states the basics for building a valid placeholder in our template strings. Every placeholder needs to be built using the $ character followed by a valid Python identifier. Take a look at the following example:

>>> template = Template(''$what, $who!'')
>>> template.substitute(what=''Hello'', who=''World'')
''Hello, World!''

Here, both placeholders are formed using valid Python identifiers (what and who). Also notice that, as stated in the second rule, the first non-identifier character terminates the placeholder as you can see in $who! where the character ! isn''t part of the placeholder, but of the final string.

There could be situations where we need to partially substitute a word in a string. That''s the reason we have a second option to build a placeholder. The third rule states that ${identifier} is equivalent to $identifier and should be used when valid identifier characters follow the placeholder but are not part of the placeholder itself.

Let''s suppose that we need to automate the creation of files containing commercial information about our company''s products. The files are named following a pattern that includes the product code, name, and production batch, all of them separated by an underscore (_) character. Consider the following example:

>>> filename_temp = Template(''$code_$product_$batch.xlsx'')
>>> filename_temp.substitute(code=''001'', product=''Apple_Juice'', batch=''zx.001.2020'')
Traceback (most recent call last):
  ...
KeyError: ''code_''

Since _ is a valid Python identifier character, our template string doesn''t work as expected and Template raises a KeyError. To correct this problem, we can use the braced notation (${identifier}) and build our placeholders as follows:

>>> filename_temp = Template(''${code}_${product}_$batch.xlsx'')
>>> filename_temp.substitute(code=''001'', product=''Apple_Juice'', batch=''zx.001.2020'')
''001_Apple_Juice_zx.001.2020.xlsx''

Now the template works correctly! That''s because the braces properly separate our identifiers from the _ character. It''s worth noting that we only need to use the braced notation for code and product and not for batch because the . character that follows batch isn''t a valid identifier character in Python.

Finally, the template string is stored in the template property of the instance. Let''s revisit the Hello, World! example, but this time we''re going to modify template a little bit:

>>> template = Template(''$what, $who!'')  # Original template
>>> template.template = ''My $what, $who template''  # Modified template
>>> template.template
''My $what, $who template''
>>> template.substitute(what=''Hello'', who=''World'')
''My Hello, World template''

Since Python doesn''t restrict the access to instance attributes, we can modify our template string to meet our needs whenever we want. However, this is not a common practice when using the Python Template class.

It''s best to create new instances of Template for every different template string we use in our code. This way, we''ll avoid some subtle and hard-to-find bugs related to the use of uncertain template strings.

The substitute() Method

So far, we''ve been using the substitute() method on a Template instance to perform string substitution. This method replaces the placeholders in a template string using keyword arguments or using a mapping containing identifier-value pairs.

The keyword arguments or the identifiers in the mapping must agree with the identifiers used to define the placeholders in the template string. The values can be any Python type that successfully converts to a string.

Since we''ve covered the use of keyword arguments in previous examples, let''s now concentrate on using dictionaries. Here''s an example:

>>> template = Template(''Hi $name, welcome to $site'')
>>> mapping = {''name'': ''John Doe'', ''site'': ''StackAbuse.com''}
>>> template.substitute(**mapping)
''Hi John Doe, welcome to StackAbuse.com''

When we use dictionaries as arguments with substitute(), we need to use the dictionary unpacking operator: **. This operator will unpack the key-value pairs into keyword arguments that will be used to substitute the matching placeholders in the template string.

Common Template Errors

There are some common errors that we can inadvertently introduce when using the Python Template class.

For example, a KeyError is raised whenever we supply an incomplete set of argument to substitute(). Consider the following code which uses an incomplete set of arguments:

>>> template = Template(''Hi $name, welcome to $site'')
>>> template.substitute(name=''Jane Doe'')
Traceback (most recent call last):
  ...
KeyError: ''site''

If we call substitute() with a set of arguments that doesn''t match all the placeholders in our template string, then we''ll get a KeyError.

If we use an invalid Python identifier in some of our placeholders, then we''ll get a ValueError telling us that the placeholder is incorrect.

Take this example where we use an invalid identifier, $0name as a placeholder instead of $name.

>>> template = Template(''Hi $0name, welcome to $site'')
>>> template.substitute(name=''Jane Doe'', site=''StackAbuse.com'')
Traceback (most recent call last):
  ...
ValueError: Invalid placeholder in string: line 1, col 4

Only when the Template object reads the template string to perform the substitution that it discovers the invalid identifier. It immediately raises a ValueError. Note that 0name isn''t a valid Python identifier or name because it starts with a digit.

The safe_substitute() Method

The Python Template class has a second method that we can use to perform string substitution. The method is called safe_substitute(). It works similarly to substitute() but when we use an incomplete or non-matching set of arguments the method doesn''t rise a KeyError.

In this case, the missing or non-matching placeholder appears unchanged in the final string.

Here''s how safe_substitute() works using an incomplete set of arguments (site will be missing):

>>> template = Template(''Hi $name, welcome to $site'')
>>> template.safe_substitute(name=''John Doe'')
''Hi John Doe, welcome to $site''

Here, we fist call safe_substitute() using an incomplete set of arguments. The resulting string contains the original placeholder $site, but no KeyError is raised.

Customizing the Python Template Class

The Python Template class is designed for subclassing and customization. This allows us to modify the regular expression patterns and other attributes of the class to meet our specific needs.

In this section, we''ll be covering how to customize some of the most important attributes of the class and how this impact the general behavior of our Template objects. Let''s start with the class attribute .delimiter.

Using a Different Delimiter

The class attribute delimiter holds the character used as the placeholder''s starting character. As we''ve seen so far, its default value is $.

Since the Python Template class is designed for inheritance, we can subclass Template and change the default value of delimiter by overriding it. Take a look at the following example where we override the delimiter to use # instead of $:

from string import Template
class MyTemplate(Template):
    delimiter = ''#''

template = MyTemplate(''Hi #name, welcome to #site'')
print(template.substitute(name=''Jane Doe'', site=''StackAbuse.com''))

# Output:
# ''Hi Jane Doe, welcome to StackAbuse.com''

# Escape operations also work
tag = MyTemplate(''This is a Twitter hashtag: ###hashtag'')
print(tag.substitute(hashtag=''Python''))

# Output:
# ''This is a Twitter hashtag: #Python''

We can use our MyTemplate class just like we use the regular Python Template class. However, we must now use # instead of $ to build our placeholders. This can be handy when we''re working with strings that handle a lot of dollar signs, for example, when we''re dealing with currencies.

Note: Do not replace a delimiter with a regular expression. The template class automatically escapes the delimiter. Therefore, if we use a regular expression as delimiter it''s highly likely that our custom Template would not work correctly.

Changing What Qualifies as an Identifier

The idpattern class attribute holds a regular expression that is used to validate the second half of a placeholder in a template string. In other words, idpattern validates that the identifiers we use in our placeholders are valid Python identifiers. The default value of idpattern is r''(?-i:[_a-zA-Z][_a-zA-Z0-9]*)''.

We can subclass Template and use our own regular expression pattern for idpattern. Suppose that we need to restrict the identifiers to names that neither contain underscores (_) nor digits ([0-9]). To do this, we can override idpattern and remove these characters from the pattern as follow:

from string import Template
class MyTemplate(Template):
    idpattern = r''(?-i:[a-zA-Z][a-zA-Z]*)''

# Underscores are not allowed
template = MyTemplate(''$name_underscore not allowed'')
print(template.substitute(name_underscore=''Jane Doe''))

If we run this code we will get this error:

Traceback (most recent call last):
    ...
KeyError: ''name''

We can confirm that digits are not allowed as well:

template = MyTemplate(''$python3 digits not allowed'')
print(template.substitute(python3=''Python version 3.x''))

The error will be:

Traceback (most recent call last):
    ...
KeyError: ''python''

Since underscore and digits are not included in our custom idpattern, the Template object applies the second rule and break the placeholder with the first non-identifier character after $. That''s why we get a KeyError in each case.

Building Advanced Template Subclasses

There could be situations where we need to modify the behavior of the Python Template class, but overriding delimiter, idpattern, or both is not enough. In these cases, we can go further and override the pattern class attribute to define an entirely new regular expression for our custom Template subclasses.

If you decide to use a whole new regular expression for pattern, then you need to provide a regular expression with four named groups:

  1. escaped matches the escape sequence for the delimiter, like in $$
  2. named matches the delimiter and a valid Python identifier, like in $identifier
  3. braced matches the delimiter and a valid Python identifier using braces, like in ${identifier}
  4. invalid matches other ill-formed delimiters, like in $0site

The pattern property holds a compiled regular expression object. However, it''s possible to inspect the original regular expression string by accessing the pattern attribute of the pattern property. Check out the following code:

>>> template = Template(''$name'')
>>> print(template.pattern.pattern)
\$(?:
    (?P<escaped>\$) |   # Escape sequence of two delimiters
    (?P<named>(?-i:[_a-zA-Z][_a-zA-Z0-9]*))      |   # delimiter and a Python identifier
    {(?P<braced>(?-i:[_a-zA-Z][_a-zA-Z0-9]*))}   |   # delimiter and a braced identifier
    (?P<invalid>)              # Other ill-formed delimiter exprs
  )

This code outputs the default string used to compile the pattern class attribute. In this case, we can clearly see the four named groups that conform to the default regular expression. As stated before, if we need to deeply customize the behavior of Template, then we should provide these same four named groups along with specific regular expressions for each group.

Running Code with eval() and exec()

Note: The built-in functions eval() and exec() can have important security implications when used with malicious input. Use with caution!

This last section is intended to open up your eyes on how powerful the Python Template class can be if we use it along with some Python built-in functions like eval() and exec().

The eval() function executes a single Python expression and returns its result. The exec() function also executes a Python expression, but it never returns its value. You normally use exec() when you''re only interested in the side-effect of an expression, like a changed variable value for example.

The examples that we''re going to cover may seem somewhat unconventional, but we''re sure that you can find some interesting use cases for this powerful combination of Python tools. They give insight into how tools that generate Python code work!

For the first example, we''re going to use a Template along with eval() to dynamically create lists via a list comprehension:

>>> template = Template(''[$exp for item in $coll]'')
>>> eval(template.substitute(exp=''item ** 2'', coll=''[1, 2, 3, 4]''))
[1, 4, 9, 16]
>>> eval(template.substitute(exp=''2 ** item'', coll=''[3, 4, 5, 6, 7, 8]''))
[8, 16, 32, 64, 128, 256]
>>> import math
>>> eval(template.substitute(expression=''math.sqrt(item)'', collection=''[9, 16, 25]''))
[3.0, 4.0, 5.0]

Our template object in this example holds the basic syntax of a list comprehension. Beginning with this template, we can dynamically create lists by substituting the placeholders with valid expressions (exp) and collections (coll). As a final step, we run the comprehension using eval().

Since there is no limit on how complex our template strings can be, it''s possible to create template strings that hold any piece of Python code. Let''s consider the following example of how to use a Template object for creating an entire class:

from string import Template

_class_template = """
class ${klass}:
    def __init__(self, name):
        self.name = name

    def ${method}(self):
        print(''Hi'', self.name + '','', ''welcome to'', ''$site'')
"""

template = Template(_class_template)
exec(template.substitute(klass=''MyClass'',
                         method=''greet'',
                         site=''StackAbuse.com''))

obj = MyClass("John Doe")
obj.greet()

Here, we create a template string to hold a fully-functional Python class. We can later use this template for creating different classes but using different names according to our needs.

In this case, exec() creates the real class and bring it to our current namespace. From this point on, we can freely use the class as we would do with any regular Python class.

Even though these examples are fairly basic, they show how powerful the Python Template class can be and how we can take advantage of it to solve complex programming problems in Python.

Conclusion

The Python Template class is intended to be used for string substitution or string interpolation. The class works using regular expressions and provides a user-friendly and powerful interface. It''s a viable alternative to other to the built-in string substitution options when it comes to creating complex string-based templates.

In this article, we''ve learned how the Python Template class works. We also learned about the more common errors that we can introduce when using Template and how to work around them. Finally, we covered how to customize the class through subclassing and how to use it to run Python code.

With this knowledge at hand, we''re in a better condition to effectively use the Python Template class to perform string interpolation or substitution in our code.

2019-02-13 Python爬虫问题 NotImplementedError: Only the following pseudo-classes are implemented: nth...

2019-02-13 Python爬虫问题 NotImplementedError: Only the following pseudo-classes are implemented: nth...

soup=BeautifulSoup(html.text,''lxml'')
#data=soup.select(''body > div.main > div.ctr > div > div.newsmcont > p:nth-of-type(3) > img'')
#data=soup.select(''body > div.main > div.ctr > div > div.newsmcont > p > img'')[2]
data=soup.select(''body > div.main > div.ctr > div > div.newsmcont > p:nth-child(3) > img'')
print(data)

当使用copy selector时,复制的是nth-child,而soup 似乎不支持nth-child,所以会报以下错误:

NotImplementedError: Only the following pseudo-classes are implemented: nth-of-type.

将nth-child 改为 nth-of-type 就可以了。

或者去掉nth-child,在后面加上[i-1],即[2]。

关于nth-child 和 nth-type,他们都是取父元素下的第n个元素,他们的区别可以通过下面这个例子了解一下:

<div> 
<ul> 
<p>zero</p> 
<li>one</li> 
<li>two</li> 
</ul> 
</div>

上面这个例子,.demo li:nth-child(2)选择的是<li>one</li>节点,.demo li:nth-of-type(2)则选择的是<li>two</li>节点。

An error happened during template parsing (template:

An error happened during template parsing (template: "class path resource [templates/index.h...

转自 https://blog.csdn.net/qq_41426326/article/details/88837112

在开发 springboot 的时候,进行 modelAndView 视图层映射的时候,一直出现 

An error happened during template parsing (template: "class path resource [templates/index.html]")

模板解析过程中发生错误 (模板:“类路径资源 [templates/index.html]”)

在向 index.html 映射的时候出现错误,小编在和其他程序员一样打开了百度开始搜索,有各种说法

1. 配置文件问题.(我重新看了一遍确定没有问题,但是还是错误)

spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.servlet.content-type=text/html
spring.thymeleaf.encoding=utf-8
spring.thymeleaf.mode=LEGACYHTML5
spring.thymeleaf.cache=false
spring.mvc.static-path-pattern=/**
spring.resources.static-locations=classpath:/static/
2. 说是 @Controller 和 @RestController 功能不一样,将 @Controller 修改为 @RestController 在加上 @ResponseBody (依然无效)、

3. 说在映射的时候实体类没有 get 方法,为变量加上 get 就可以了(结果我本来就有 get 方法的)

4. 还有说在 pom.xml 文件下的 build 配置 (都不是这个错误的解决方案)

<resources>
<resource>
<directory>sre/main/resources</directory>
</resource>
</resources>
最后小编早上智商最高峰的时候发现了这个小小小问题

 

在这附上小编 index.html 的文件开头,就是因为加了

https: xmlns:https="http://www.w3.org/1999/xhtml"

xmlns:th="http://www.thymeleaf.org"
导致调用的时候原本要调用第二句话的代码调用了第一句代码中的方法发生错误,把第一句代码删除就可以了

小编总结了一下,一般系统出现以下错误

An error happened during template parsing (template: "class path resource [templates/index.html]")

大家可以去看看视图层,并不是 java 代码出现错误.

An error happened during template parsing (template: "class path resource [templates/user.html]

An error happened during template parsing (template: "class path resource [templates/user.html]

问题:

An error happened during template parsing (template: "class path resource [templates/user.html]")

 

 解决方法:

1.配置文件问题。根据问题描述,问题可能为想要去的地址路径错误。解决方法:修改路径。

 

 

 

 2.@RestController

@RestController相当于@Response + @Controller,作用是将return的字符串响应在界面上。

而@Controller作用是将return中的字符串拼接配置文件中的前后缀,形成一个html地址,最后在网页上指向这个地址界面。

 两者作用不同。

 

3.为变量加上get

实体类中可能没有getter and setter方法,加上。

或者可能是LomBok出问题了,重启或者刷新maven包可能可以解决。

 

4.xmlns冲突。可能同时设置了 “https: xmlns:https="http://www.w3.org/1999/xhtml" ”和 “xmlns:th="http://www.thymeleaf.org" ”。删去“https: xmlns:https="http://www.w3.org/1999/xhtml" ”即可。

 

5.(我的问题)进行select搜索时,数据库中没有id=“111”这个数据!所以导致页面跳转指向不明,导致错误TAT

 

高了,血压高了!!!

 

写代码须细心啊TAT

   

AttributeError: 'Settings' object has no attribute 'TEMPLATE_CONTEXT_PROCESSORS'

AttributeError: 'Settings' object has no attribute 'TEMPLATE_CONTEXT_PROCESSORS'

使用Xadmin,执行makemigrations和migrate时运行报错提示:

AttributeError: ''Settings'' object has no attribute ''TEMPLATE_CONTEXT_PROCESSORS''

第一个解决办法:

setting.py文件添加以下信息:

TEMPLATE_CONTEXT_PROCESSORS = (
 ''django.contrib.auth.context_processors.auth'', ''django.core.context_processors.auth''
 ''django.core.context_processors.debug'', ''django.core.context_processors.media'', ''django.core.context_processors.static'', ''django.core.context_processors.tz'', ''django.contrib.messages.context_processors.messages'', ''learn_models.context_processors.test'',)

第二个解决办法:

https://github.com/sshwsfc/xadmin下载源码,因为github该Bug被修复了,而pypi没有更新导致的。

今天关于Formatting Strings with the Python Template Class的讲解已经结束,谢谢您的阅读,如果想了解更多关于2019-02-13 Python爬虫问题 NotImplementedError: Only the following pseudo-classes are implemented: nth...、An error happened during template parsing (template: "class path resource [templates/index.h...、An error happened during template parsing (template: "class path resource [templates/user.html]、AttributeError: 'Settings' object has no attribute 'TEMPLATE_CONTEXT_PROCESSORS'的相关知识,请在本站搜索。

本文标签: