<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://kodi.wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Roman+V+M</id>
	<title>Official Kodi Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://kodi.wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Roman+V+M"/>
	<link rel="alternate" type="text/html" href="https://kodi.wiki/view/Special:Contributions/Roman_V_M"/>
	<updated>2026-06-19T09:17:07Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=243731</id>
		<title>Python tv scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=243731"/>
		<updated>2023-01-21T22:38:35Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
&lt;br /&gt;
A TV shows scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific TV show by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a TV show poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl (TV show)==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; file is present in a TV show directory.&lt;br /&gt;
The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV show information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique ID from the TV information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online TV show databases. This is needed to correctly get TV show&#039;s artwork.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;episodeguide&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setInfo()&amp;lt;/code&amp;gt; instance method. This should be some unique string that can be used to retrieve the list of TV show episoded with all the necessary info.&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; contains all the necessary info about the respective TV show in XML format then this actions may not pass any &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
In this case Kodi will use all the information parsed from the XML file and will not call &#039;&#039;&#039;getdetails&#039;&#039;&#039; action.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl (episode)==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is also called as for each episode .NFO file that is present in a TV show directory.&lt;br /&gt;
The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary episode info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to the episode page on a TV show information website or some unique ID to request episode information from a REST API.&lt;br /&gt;
&lt;br /&gt;
If an episode .NFO file contains all the necessary info about the respective episode in XML format then this action may not pass any &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
In this case Kodi will use all the information parsed from the XML file and will not call &#039;&#039;&#039;getepisodedetails&#039;&#039;&#039; action.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
One of the necessary properties that are set via &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt;. This should be some unique string that can be used to retrieve&lt;br /&gt;
the list of TV show episoded with all the necessary info.&lt;br /&gt;
&lt;br /&gt;
==getepisodelist==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodelist&amp;lt;/code&amp;gt; action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi&lt;br /&gt;
with information about available TV show episodes. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter that is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; property set by &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt;action.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This is some unique string that can be used to retrieve information about a specific episode.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;season&#039;&#039;&#039;: season number that is passed via &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;episode&#039;&#039;&#039;: episode number that is passed &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;aired&#039;&#039;&#039;: episode air date (if available) that is passed &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
==getepisodedetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodedetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stage and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getartwork&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions or parsed form an XML &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; file if the scraper haven&#039;t set any. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your .NFO file contains the default unique ID that is different from the ID of the TV show database your scraper works with,&lt;br /&gt;
you must set the correct default unique ID in &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action. Otherwise &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; will receive the default unique ID from your .NFO file&lt;br /&gt;
and your scraper may not be able to find any artwork using this ID.&lt;br /&gt;
&lt;br /&gt;
=episodeguide=&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; string is passed to &amp;lt;code&amp;gt;getepisodedetails&amp;lt;/code&amp;gt; action to retrieve the list of episodes. In legacy XML scrapers it was an actual URL of a page that was supposed to contain&lt;br /&gt;
the list of TV show episodes. Now in Python scrapers it can be any string that allows to correctly identify a TV show and retrieve the list of its episodes. However, the commonly accepted convention for &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; is that it should be a JSON-encoded string containing IDs of the specific TV show in various online databases. As a minimum it should include the ID of a show at the database&lt;br /&gt;
the scraper works with. An example of a JSON-encoded &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; string:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;{&amp;quot;tvmaze&amp;quot;: &amp;quot;60&amp;quot;, &amp;quot;tvrage&amp;quot;: &amp;quot;4628&amp;quot;, &amp;quot;tvdb&amp;quot;: &amp;quot;72108&amp;quot;, &amp;quot;imdb&amp;quot;: &amp;quot;tt0364845&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that all IDs should be strings.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example TV Shows Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python TV show scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.tv metadata.demo.tv addon].&lt;br /&gt;
&lt;br /&gt;
[[Category:Scraper]]&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=243730</id>
		<title>Python tv scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=243730"/>
		<updated>2023-01-21T22:33:05Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
&lt;br /&gt;
A TV shows scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific TV show by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a TV show poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl (TV show)==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; file is present in a TV show directory.&lt;br /&gt;
The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV show information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique ID from the TV information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online TV show databases. This is needed to correctly get TV show&#039;s artwork.&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; contains all the necessary info about the respective TV show in XML format then this actions may not pass any &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
In this case Kodi will use all the information parsed from the XML file and will not call &#039;&#039;&#039;getdetails&#039;&#039;&#039; action.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl (episode)==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is also called as for each episode .NFO file that is present in a TV show directory.&lt;br /&gt;
The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary episode info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to the episode page on a TV show information website or some unique ID to request episode information from a REST API.&lt;br /&gt;
&lt;br /&gt;
If an episode .NFO file contains all the necessary info about the respective episode in XML format then this action may not pass any &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
In this case Kodi will use all the information parsed from the XML file and will not call &#039;&#039;&#039;getepisodedetails&#039;&#039;&#039; action.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
One of the necessary properties that are set via &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt;. This should be some unique string that can be used to retrieve&lt;br /&gt;
the list of TV show episoded with all the necessary info.&lt;br /&gt;
&lt;br /&gt;
==getepisodelist==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodelist&amp;lt;/code&amp;gt; action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi&lt;br /&gt;
with information about available TV show episodes. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter that is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; property set by &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt;action.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This is some unique string that can be used to retrieve information about a specific episode.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;season&#039;&#039;&#039;: season number that is passed via &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;episode&#039;&#039;&#039;: episode number that is passed &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;aired&#039;&#039;&#039;: episode air date (if available) that is passed &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
==getepisodedetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodedetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stage and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getartwork&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions or parsed form an XML &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; file if the scraper haven&#039;t set any. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your .NFO file contains the default unique ID that is different from the ID of the TV show database your scraper works with,&lt;br /&gt;
you must set the correct default unique ID in &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action. Otherwise &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; will receive the default unique ID from your .NFO file&lt;br /&gt;
and your scraper may not be able to find any artwork using this ID.&lt;br /&gt;
&lt;br /&gt;
=episodeguide=&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; string is passed to &amp;lt;code&amp;gt;getepisodedetails&amp;lt;/code&amp;gt; action to retrieve the list of episodes. In legacy XML scrapers it was an actual URL of a page that was supposed to contain&lt;br /&gt;
the list of TV show episodes. Now in Python scrapers it can be any string that allows to correctly identify a TV show and retrieve the list of its episodes. However, the commonly accepted convention for &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; is that it should be a JSON-encoded string containing IDs of the specific TV show in various online databases. As a minimum it should include the ID of a show at the database&lt;br /&gt;
the scraper works with. An example of a JSON-encoded &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; string:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;{&amp;quot;tvmaze&amp;quot;: &amp;quot;60&amp;quot;, &amp;quot;tvrage&amp;quot;: &amp;quot;4628&amp;quot;, &amp;quot;tvdb&amp;quot;: &amp;quot;72108&amp;quot;, &amp;quot;imdb&amp;quot;: &amp;quot;tt0364845&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that all IDs should be strings.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example TV Shows Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python TV show scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.tv metadata.demo.tv addon].&lt;br /&gt;
&lt;br /&gt;
[[Category:Scraper]]&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=243729</id>
		<title>Python tv scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=243729"/>
		<updated>2023-01-21T22:30:42Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
&lt;br /&gt;
A TV shows scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific TV show by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a TV show poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl (TV show)==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; file is present in a TV show directory.&lt;br /&gt;
The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV show information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique ID from the TV information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online TV show databases. This is needed to correctly get TV show&#039;s artwork.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;episodeguide&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setInfo()&amp;lt;/code&amp;gt; instance method. A scraper should set &#039;&#039;&#039;episodeguide&#039;&#039;&#039; string that will allow to get the list of episodes from data provider&#039;s website or API.&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; contains all the necessary info about the respective TV show in XML format then this actions may not pass any &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
In this case Kodi will use all the information parsed from the XML file and will not call &#039;&#039;&#039;getdetails&#039;&#039;&#039; action.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl (episode)==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is also called as for each episode .NFO file that is present in a TV show directory.&lt;br /&gt;
The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary episode info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to the episode page on a TV show information website or some unique ID to request episode information from a REST API.&lt;br /&gt;
&lt;br /&gt;
If an episode .NFO file contains all the necessary info about the respective episode in XML format then this action may not pass any &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
In this case Kodi will use all the information parsed from the XML file and will not call &#039;&#039;&#039;getepisodedetails&#039;&#039;&#039; action.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
One of the necessary properties that are set via &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt;. This should be some unique string that can be used to retrieve&lt;br /&gt;
the list of TV show episoded with all the necessary info.&lt;br /&gt;
&lt;br /&gt;
==getepisodelist==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodelist&amp;lt;/code&amp;gt; action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi&lt;br /&gt;
with information about available TV show episodes. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter that is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; property set by &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt;action.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This is some unique string that can be used to retrieve information about a specific episode.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;season&#039;&#039;&#039;: season number that is passed via &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;episode&#039;&#039;&#039;: episode number that is passed &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;aired&#039;&#039;&#039;: episode air date (if available) that is passed &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
==getepisodedetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodedetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stage and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getartwork&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions or parsed form an XML &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; file if the scraper haven&#039;t set any. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your .NFO file contains the default unique ID that is different from the ID of the TV show database your scraper works with,&lt;br /&gt;
you must set the correct default unique ID in &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action. Otherwise &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; will receive the default unique ID from your .NFO file&lt;br /&gt;
and your scraper may not be able to find any artwork using this ID.&lt;br /&gt;
&lt;br /&gt;
=episodeguide=&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; string is passed to &amp;lt;code&amp;gt;getepisodedetails&amp;lt;/code&amp;gt; action to retrieve the list of episodes. In legacy XML scrapers it was an actual URL of a page that was supposed to contain&lt;br /&gt;
the list of TV show episodes. Now in Python scrapers it can be any string that allows to correctly identify a TV show and retrieve the list of its episodes. However, the commonly accepted convention for &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; is that it should be a JSON-encoded string containing IDs of the specific TV show in various online databases. As a minimum it should include the ID of a show at the database&lt;br /&gt;
the scraper works with. An example of a JSON-encoded &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; string:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;{&amp;quot;tvmaze&amp;quot;: &amp;quot;60&amp;quot;, &amp;quot;tvrage&amp;quot;: &amp;quot;4628&amp;quot;, &amp;quot;tvdb&amp;quot;: &amp;quot;72108&amp;quot;, &amp;quot;imdb&amp;quot;: &amp;quot;tt0364845&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that all IDs should be strings.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example TV Shows Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python TV show scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.tv metadata.demo.tv addon].&lt;br /&gt;
&lt;br /&gt;
[[Category:Scraper]]&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=243728</id>
		<title>Python tv scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=243728"/>
		<updated>2023-01-21T22:29:51Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
&lt;br /&gt;
A TV shows scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific TV show by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a TV show poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl (TV show)==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; file is present in a TV show directory.&lt;br /&gt;
The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV show information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique ID from the TV information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online TV show databases. This is needed to correctly get TV show&#039;s artwork.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;episodeguide&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setInfo()&amp;lt;/code&amp;gt; instance method. A scraper should set &#039;&#039;&#039;episodeguide&#039;&#039;&#039; string that will allow to get the list of episodes from data provider&#039;s&lt;br /&gt;
website or API.&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; contains all the necessary info about the respective TV show in XML format then this actions may not pass any &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
In this case Kodi will use all the information parsed from the XML file and will not call &#039;&#039;&#039;getdetails&#039;&#039;&#039; action.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl (episode)==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is also called as for each episode .NFO file that is present in a TV show directory.&lt;br /&gt;
The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary episode info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to the episode page on a TV show information website or some unique ID to request episode information from a REST API.&lt;br /&gt;
&lt;br /&gt;
If an episode .NFO file contains all the necessary info about the respective episode in XML format then this action may not pass any &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
In this case Kodi will use all the information parsed from the XML file and will not call &#039;&#039;&#039;getepisodedetails&#039;&#039;&#039; action.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
One of the necessary properties that are set via &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt;. This should be some unique string that can be used to retrieve&lt;br /&gt;
the list of TV show episoded with all the necessary info.&lt;br /&gt;
&lt;br /&gt;
==getepisodelist==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodelist&amp;lt;/code&amp;gt; action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi&lt;br /&gt;
with information about available TV show episodes. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter that is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; property set by &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt;action.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This is some unique string that can be used to retrieve information about a specific episode.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;season&#039;&#039;&#039;: season number that is passed via &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;episode&#039;&#039;&#039;: episode number that is passed &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;aired&#039;&#039;&#039;: episode air date (if available) that is passed &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
==getepisodedetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodedetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stage and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getartwork&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions or parsed form an XML &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; file if the scraper haven&#039;t set any. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your .NFO file contains the default unique ID that is different from the ID of the TV show database your scraper works with,&lt;br /&gt;
you must set the correct default unique ID in &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action. Otherwise &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; will receive the default unique ID from your .NFO file&lt;br /&gt;
and your scraper may not be able to find any artwork using this ID.&lt;br /&gt;
&lt;br /&gt;
=episodeguide=&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; string is passed to &amp;lt;code&amp;gt;getepisodedetails&amp;lt;/code&amp;gt; action to retrieve the list of episodes. In legacy XML scrapers it was an actual URL of a page that was supposed to contain&lt;br /&gt;
the list of TV show episodes. Now in Python scrapers it can be any string that allows to correctly identify a TV show and retrieve the list of its episodes. However, the commonly accepted convention for &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; is that it should be a JSON-encoded string containing IDs of the specific TV show in various online databases. As a minimum it should include the ID of a show at the database&lt;br /&gt;
the scraper works with. An example of a JSON-encoded &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; string:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;{&amp;quot;tvmaze&amp;quot;: &amp;quot;60&amp;quot;, &amp;quot;tvrage&amp;quot;: &amp;quot;4628&amp;quot;, &amp;quot;tvdb&amp;quot;: &amp;quot;72108&amp;quot;, &amp;quot;imdb&amp;quot;: &amp;quot;tt0364845&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that all IDs should be strings.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example TV Shows Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python TV show scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.tv metadata.demo.tv addon].&lt;br /&gt;
&lt;br /&gt;
[[Category:Scraper]]&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=243520</id>
		<title>Python tv scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=243520"/>
		<updated>2023-01-03T15:20:26Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
&lt;br /&gt;
A TV shows scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific TV show by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a TV show poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl (TV show)==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; file is present in a TV show directory.&lt;br /&gt;
The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV show information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique ID from the TV information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online TV show databases.&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; contains all the necessary info about the respective TV show in XML format then this actions may not pass any &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
In this case Kodi will use all the information parsed from the XML file and will not call &#039;&#039;&#039;getdetails&#039;&#039;&#039; action.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl (episode)==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is also called as for each episode .NFO file that is present in a TV show directory.&lt;br /&gt;
The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary episode info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to the episode page on a TV show information website or some unique ID to request episode information from a REST API.&lt;br /&gt;
&lt;br /&gt;
If an episode .NFO file contains all the necessary info about the respective episode in XML format then this action may not pass any &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
In this case Kodi will use all the information parsed from the XML file and will not call &#039;&#039;&#039;getepisodedetails&#039;&#039;&#039; action.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
One of the necessary properties that are set via &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt;. This should be some unique string that can be used to retrieve&lt;br /&gt;
the list of TV show episoded with all the necessary info.&lt;br /&gt;
&lt;br /&gt;
==getepisodelist==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodelist&amp;lt;/code&amp;gt; action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi&lt;br /&gt;
with information about available TV show episodes. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter that is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; property set by &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt;action.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This is some unique string that can be used to retrieve information about a specific episode.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;season&#039;&#039;&#039;: season number that is passed via &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;episode&#039;&#039;&#039;: episode number that is passed &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;aired&#039;&#039;&#039;: episode air date (if available) that is passed &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
==getepisodedetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodedetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stage and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getartwork&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions or parsed form an XML &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; file if the scraper haven&#039;t set any. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your .NFO file contains the default unique ID that is different from the ID of the TV show database your scraper works with,&lt;br /&gt;
you must set the correct default unique ID in &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action. Otherwise &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; will receive the default unique ID from your .NFO file&lt;br /&gt;
and your scraper may not be able to find any artwork using this ID.&lt;br /&gt;
&lt;br /&gt;
=episodeguide=&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; string is passed to &amp;lt;code&amp;gt;getepisodedetails&amp;lt;/code&amp;gt; action to retrieve the list of episodes. In legacy XML scrapers it was an actual URL of a page that was supposed to contain&lt;br /&gt;
the list of TV show episodes. Now in Python scrapers it can be any string that allows to correctly identify a TV show and retrieve the list of its episodes. However, the commonly accepted convention for &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; is that it should be a JSON-encoded string containing IDs of the specific TV show in various online databases. As a minimum it should include the ID of a show at the database&lt;br /&gt;
the scraper works with. An example of a JSON-encoded &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; string:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;{&amp;quot;tvmaze&amp;quot;: &amp;quot;60&amp;quot;, &amp;quot;tvrage&amp;quot;: &amp;quot;4628&amp;quot;, &amp;quot;tvdb&amp;quot;: &amp;quot;72108&amp;quot;, &amp;quot;imdb&amp;quot;: &amp;quot;tt0364845&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that all IDs should be strings.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example TV Shows Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python TV show scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.tv metadata.demo.tv addon].&lt;br /&gt;
&lt;br /&gt;
[[Category:Scraper]]&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=HOW-TO:Debug_Python_Scripts_with_Web-PDB&amp;diff=242910</id>
		<title>HOW-TO:Debug Python Scripts with Web-PDB</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=HOW-TO:Debug_Python_Scripts_with_Web-PDB&amp;diff=242910"/>
		<updated>2022-09-02T17:53:13Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Development]]|[[Add-on development]]|[[Python development]]}}&lt;br /&gt;
&lt;br /&gt;
[https://github.com/romanvm/kodi.web-pdb Web-PDB] is a remote web-interface to Python&#039;s built-in [https://docs.python.org/3/library/pdb.html PDB] debugger with additional convenience features. It is not tied to any IDE or other software, all you need is a common web-browser, e.g. Chrome or Firefox. Web-PDB is compatible with both Python 2 and 3, so you can use it to debug your Python 3 compatible addons.&lt;br /&gt;
&lt;br /&gt;
[[File:web-pdb.png]]&lt;br /&gt;
&lt;br /&gt;
Web-PDB for Kodi is available as an addon in the official Kodi addons repo.&lt;br /&gt;
&lt;br /&gt;
== How To Use Web-PDB for Kodi ==&lt;br /&gt;
&lt;br /&gt;
1. Install Web-PDB addon: &#039;&#039;&#039;Kodi Add-on repository &amp;gt; Program add-ons &amp;gt; Web-PDB&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
2. Add &amp;lt;code&amp;gt;script.module.web-pdb&amp;lt;/code&amp;gt; to [[addon.xml]] as a dependency:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;requires&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
   &amp;lt;import addon=&amp;quot;script.module.web-pdb&amp;quot; version=&amp;quot;1.5.6&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;requires&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. Restart Kodi so that it re-reads addon dependencies.&lt;br /&gt;
&lt;br /&gt;
4. Insert the following line into your addon code at the point where you want to start debugging:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
import web_pdb; web_pdb.set_trace()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;set_trace()&amp;lt;/code&amp;gt; call will suspend your addon and open a web-UI at the default port 5555 (port value can be changed). At the same time a notification will be displayed in Kodi, indicating that a debug session is active. The notification also shows web-UI host/port.&lt;br /&gt;
&lt;br /&gt;
5. Enter in your the address bar of your browser: &amp;lt;code&amp;gt;http://&amp;lt;your Kodi machine hostname or IP&amp;gt;:5555&amp;lt;/code&amp;gt;, for example &amp;lt;code&amp;gt;http://monty-python:5555&amp;lt;/code&amp;gt;. Use &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt; as a hostname if you are connecting from the same machine that runs Kodi. If everything is OK, you should see the Web-PDB UI. Now you can use all PDB commands and features. Additional &#039;&#039;&#039;Current file&#039;&#039;&#039;, &#039;&#039;&#039;Globals&#039;&#039;&#039; and &#039;&#039;&#039;Locals&#039;&#039;&#039; information boxes help you better track your program runtime state.&lt;br /&gt;
&lt;br /&gt;
== More Information ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/romanvm/kodi.web-pdb Web-PDB for Kodi on GitHub].&lt;br /&gt;
* [https://docs.python.org/3.10/library/pdb.html PDB debugger documentation].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Python]]&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_Problems&amp;diff=242904</id>
		<title>Python Problems</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_Problems&amp;diff=242904"/>
		<updated>2022-09-01T19:44:30Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Mininav|[[Development]]|[[Add-on development]]|[[About Add-ons]]}}&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page is meant to document Python issues of general interest to Kodi addon developers.&lt;br /&gt;
&lt;br /&gt;
== datetime.strptime ==&lt;br /&gt;
There is an old [[Python debugging|Python bug]]&amp;lt;ref name=&amp;quot;bug_27400&amp;quot; /&amp;gt; which &#039;&#039;only&#039;&#039; impacts embedded Python applications, such as the Kodi Python environment. The issue is that &amp;lt;code&amp;gt;datetime.strptime&amp;lt;/code&amp;gt;&amp;lt;ref name=&amp;quot;pydocs_datetime&amp;quot; /&amp;gt; is only initialized once per process, and not every time the embedded environment is reinitialized. This causes &amp;lt;code&amp;gt;datetime.strptime&amp;lt;/code&amp;gt; to return &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; (and perhaps other strange behavior).&lt;br /&gt;
&lt;br /&gt;
=== Workaround ===&lt;br /&gt;
The workaround is to monkey-patch &amp;lt;code&amp;gt;datetime.strptime&amp;lt;/code&amp;gt; so that any user of the Python runtime will use it. It is more voodoo-like, but situations like this are why Python &#039;&#039;natively supports&#039;&#039; [[wikipedia:Monkey patch|monkey patching]], after all. The typically excellent Python documentation manages to be both thorough and concise simultaneously with regards to &amp;lt;code&amp;gt;datetime.strptime&amp;lt;/code&amp;gt; and is well worth reviewing before deciding which angle of attack best suits your use case.&amp;lt;ref name=&amp;quot;pydocs_strptime&amp;quot; /&amp;gt;; it discusses some of the differences between &amp;lt;code&amp;gt;datetime.strptime&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;time.strptime&amp;lt;/code&amp;gt;.&amp;lt;ref name=&amp;quot;pydocs_differences&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Patch ===&lt;br /&gt;
This patch simply replaces &amp;lt;code&amp;gt;datetime.strptime&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;time.strptime&amp;lt;/code&amp;gt; as they are nearly identical in function. The original Kodi-specific implementation and its commit history are available on GitHub as part of &amp;lt;code&amp;gt;script.module.kutils&amp;lt;/code&amp;gt;.&amp;lt;ref name=&amp;quot;kutils_source&amp;quot; /&amp;gt; Essentially, the patch is:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import datetime&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class proxydt(datetime.datetime):&lt;br /&gt;
&lt;br /&gt;
    @classmethod&lt;br /&gt;
    def strptime(cls, date_string, format):&lt;br /&gt;
        return datetime.datetime(*(time.strptime(date_string, format)[:6]))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
datetime.datetime = proxydt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== asyncio ==&lt;br /&gt;
&lt;br /&gt;
It is a known [https://github.com/python/cpython/issues/91375 issue] that &amp;lt;code&amp;gt;asyncio&amp;lt;/code&amp;gt; module or rather its C-based implementation does not support embedded Python environments that use sub-interpreters, such as Kodi Python environment. Essentially it means that only one addon can start the event loop by calling &amp;lt;code&amp;gt;asyncio.run()&amp;lt;/code&amp;gt; and others will fail with &amp;lt;code&amp;gt;RuntimeError&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Workaround ===&lt;br /&gt;
&lt;br /&gt;
The workaround is to disable C-based &amp;lt;code&amp;gt;asyncio&amp;lt;/code&amp;gt; module and use its pure-Python implementation. This can be done by the following code that should be put at the beginning of your addon entrypoint script:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
sys.modules[&#039;_asyncio&#039;] = None&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will loose possible performance benefits of &amp;lt;code&amp;gt;asyncio&amp;lt;/code&amp;gt; but your async Python code won&#039;t fail.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;div  class=&amp;quot;plainlinks&amp;quot;&amp;gt;&amp;lt;references&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;bug_27400&amp;quot;&amp;gt;Weinberg, Denny ({{#Dateformat:2016-06-27|mdy}}). [https://github.com/python/cpython/issues/71587 &#039;&#039;&#039;Issue #71587: Datetime NoneType after calling Py_Finalize and Py_Initialize&#039;&#039;&#039;]. [https://github.com/python/cpython/issues &#039;&#039;Python Issue Tracker&#039;&#039;] on [https://github.com/ GitHub].&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;pydocs_datetime&amp;quot;&amp;gt;[https://docs.python.org/3/ &amp;lt;span style=&amp;quot;text-decoration: underline;&amp;quot;&amp;gt;Python 3 Documentation&amp;lt;/span&amp;gt;] ({{#dateformat:2022-08-28|mdy}}). [https://docs.python.org/3/library/index.html The Python Standard Library] » [https://docs.python.org/3/library/datatypes.html Data Types] » [https://docs.python.org/3/library/datetime.html#module-datetime datetime — Basic date and time types] ― &amp;lt;span style=&amp;quot;font-weight: 600;&amp;quot;&amp;gt;[https://docs.python.org/3/library/datetime.html#datetime.datetime.strptime &#039;&#039;classmethod&#039;&#039; &amp;lt;kbd&amp;gt;datetime.&#039;&#039;&#039;strptime&#039;&#039;&#039;(&#039;&#039;date_string, format&#039;&#039;)&amp;lt;/kbd&amp;gt;]&amp;lt;/span&amp;gt; ― from the source code found in [https://github.com/python/cpython/blob/main/Lib/datetime.py Lib/datetime.py].&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;pydocs_strptime&amp;quot;&amp;gt;[https://docs.python.org/3/ &amp;lt;span style=&amp;quot;text-decoration: underline;&amp;quot;&amp;gt;Python 3 Documentation&amp;lt;/span&amp;gt;] ({{#dateformat:2022-08-28|mdy}}). datetime — Basic date and time types » &amp;lt;span style=&amp;quot;font-weight: 600;&amp;quot;&amp;gt;[https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior &amp;lt;kbd&amp;gt;strftime()&amp;lt;/kbd&amp;gt; and &amp;lt;kbd&amp;gt;strptime()&amp;lt;/kbd&amp;gt; Behavior]&amp;lt;/span&amp;gt;.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;pydocs_differences&amp;quot;&amp;gt;[https://docs.python.org/3/ &amp;lt;span style=&amp;quot;text-decoration: underline;&amp;quot;&amp;gt;Python 3 Documentation&amp;lt;/span&amp;gt;] ({{#dateformat:2022-08-28|mdy}}). &amp;lt;kbd&amp;gt;strftime()&amp;lt;/kbd&amp;gt; and &amp;lt;kbd&amp;gt;strptime()&amp;lt;/kbd&amp;gt; Behavior » &amp;lt;span style=&amp;quot;font-weight: 600;&amp;quot;&amp;gt;[https://docs.python.org/3.10/library/datetime.html#technical-detail Technical Detail]&amp;lt;/span&amp;gt;.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;kutils_source&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;font-weight: 600;&amp;quot;&amp;gt;[https://github.com/fbacher/script.module.kutils/blob/master/lib/kutils/strptime_patch.py &amp;lt;kbd&amp;gt;lib/kutils/strptime_patch.py&amp;lt;/kbd&amp;gt;]&amp;lt;/span&amp;gt; ({{#dateformat:2022-01-11|mdy}}) in &amp;lt;code&amp;gt;script.module.kutils&amp;lt;/code&amp;gt;, &#039;&#039;&amp;quot;A helper module for Kodi development&amp;quot;&#039;&#039; on GitHub.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;/references&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Python]]&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=242794</id>
		<title>Python tv scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=242794"/>
		<updated>2022-08-13T22:17:28Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
&lt;br /&gt;
A TV shows scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific TV show by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a TV show poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl (TV show)==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; file is present in a TV show directory.&lt;br /&gt;
The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV show information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique ID from the TV information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online TV show databases.&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; contains all the necessary info about the respective TV show in XML format then this actions may not pass any &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
In this case Kodi will use all the information parsed from the XML file and will not call &#039;&#039;&#039;getdetails&#039;&#039;&#039; action.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl (episode)==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is also called as for each episode .NFO file that is present in a TV show directory.&lt;br /&gt;
The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary episode info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to the episode page on a TV show information website or some unique ID to request episode information from a REST API.&lt;br /&gt;
&lt;br /&gt;
If an episode .NFO file contains all the necessary info about the respective episode in XML format then this action may not pass any &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
In this case Kodi will use all the information parsed from the XML file and will not call &#039;&#039;&#039;getepisodedetails&#039;&#039;&#039; action.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
One of the necessary properties that are set via &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt;. This should be some unique string that can be used to retrieve&lt;br /&gt;
the list of TV show episoded with all the necessary info.&lt;br /&gt;
&lt;br /&gt;
==getepisodelist==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodelist&amp;lt;/code&amp;gt; action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi&lt;br /&gt;
with information about available TV show episodes. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter that is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; property set by &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This is some unique string that can be used to retrieve information about a specific episode.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;season&#039;&#039;&#039;: season number that is passed via &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;episode&#039;&#039;&#039;: episode number that is passed &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;aired&#039;&#039;&#039;: episode air date (if available) that is passed &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
==getepisodedetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodedetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stage and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getartwork&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions or parsed form an XML &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; file if the scraper haven&#039;t set any. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your .NFO file contains the default unique ID that is different from the ID of the TV show database your scraper works with,&lt;br /&gt;
you must set the correct default unique ID in &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action. Otherwise &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; will receive the default unique ID from your .NFO file&lt;br /&gt;
and your scraper may not be able to find any artwork using this ID.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example TV Shows Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python TV show scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.tv metadata.demo.tv addon].&lt;br /&gt;
&lt;br /&gt;
[[Category:Scraper]]&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242766</id>
		<title>Python movie scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242766"/>
		<updated>2022-08-05T11:47:33Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
&lt;br /&gt;
A movie scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific movie by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a movie poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if an .NFO file is present along with a movie file. The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;&lt;br /&gt;
parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique ID from the movie information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online movie databases.&lt;br /&gt;
&lt;br /&gt;
If an .NFO contains all the necessary info about the respective movie in XML format then this actions may not pass any &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
In this case Kodi will use all the information parsed from the XML file and will not call &#039;&#039;&#039;getdetails&#039;&#039;&#039; action.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getartwork&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt;&lt;br /&gt;
and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your .NFO file contains the default unique ID that is different from the ID of the movie database your scraper works with,&lt;br /&gt;
you must set the correct default unique ID in &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action. Otherwise &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; will receive the default unique ID from your .NFO file&lt;br /&gt;
and your scraper may not be able to find any artwork using this ID.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example Movie Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python movie scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.movies metadata.demo.movie addon].&lt;br /&gt;
&lt;br /&gt;
[[Category:Scraper]]&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242765</id>
		<title>Python movie scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242765"/>
		<updated>2022-08-05T11:47:03Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
&lt;br /&gt;
A movie scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific movie by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a movie poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if an .NFO file is present along with a movie file. The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;&lt;br /&gt;
parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique ID from the movie information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online movie databases.&lt;br /&gt;
&lt;br /&gt;
If an .NFO contains all the necessary info about the respective TV show in XML format then this actions may not pass any &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
In this case Kodi will use all the information parsed from the XML file and will not call &#039;&#039;&#039;getdetails&#039;&#039;&#039; action.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getartwork&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt;&lt;br /&gt;
and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your .NFO file contains the default unique ID that is different from the ID of the movie database your scraper works with,&lt;br /&gt;
you must set the correct default unique ID in &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action. Otherwise &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; will receive the default unique ID from your .NFO file&lt;br /&gt;
and your scraper may not be able to find any artwork using this ID.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example Movie Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python movie scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.movies metadata.demo.movie addon].&lt;br /&gt;
&lt;br /&gt;
[[Category:Scraper]]&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=242764</id>
		<title>Python tv scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=242764"/>
		<updated>2022-08-04T20:54:26Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
&lt;br /&gt;
A TV shows scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific TV show by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a TV show poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl (TV show)==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; file is present in a TV show directory.&lt;br /&gt;
The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV show information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique ID from the TV information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online TV show databases.&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; contains all the necessary info about the respective TV show in XML format then this actions may not pass any &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
In this case Kodi will use all the information parsed from the XML file and will not call &#039;&#039;&#039;getdetails&#039;&#039;&#039; action.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl (episode)==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is also called as for each episode .NFO file that is present in a TV show directory.&lt;br /&gt;
The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary episode info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to the episode page on a TV show information website or some unique ID to request episode information from a REST API.&lt;br /&gt;
&lt;br /&gt;
If an episode .NFO file contains all the necessary info about the respective episode in XML format then this action may not pass any &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
In this case Kodi will use all the information parsed from the XML file and will not call &#039;&#039;&#039;getepisodedetails&#039;&#039;&#039; action.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
One of the necessary properties that are set via &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt;. This should be some unique string that can be used to retrieve&lt;br /&gt;
the list of TV show episoded with all the necessary info.&lt;br /&gt;
&lt;br /&gt;
==getepisodelist==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodelist&amp;lt;/code&amp;gt; action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi&lt;br /&gt;
with information about available TV show episodes. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter that is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; property set by &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action.&lt;br /&gt;
A scraper needs to set &#039;&#039;&#039;url&#039;&#039;&#039; for each &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance that is some unique string that can be used to retrieve information about a specific episode.&lt;br /&gt;
&lt;br /&gt;
==getepisodedetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodedetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stage and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getartwork&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions or parsed form an XML &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; file if the scraper haven&#039;t set any. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your .NFO file contains the default unique ID that is different from the ID of the TV show database your scraper works with,&lt;br /&gt;
you must set the correct default unique ID in &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action. Otherwise &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; will receive the default unique ID from your .NFO file&lt;br /&gt;
and your scraper may not be able to find any artwork using this ID.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example TV Shows Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python TV show scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.tv metadata.demo.tv addon].&lt;br /&gt;
&lt;br /&gt;
[[Category:Scraper]]&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=242763</id>
		<title>Python tv scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=242763"/>
		<updated>2022-08-04T20:53:33Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
&lt;br /&gt;
A TV shows scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific TV show by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a TV show poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl (TV show)==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; file is present in a TV show directory.&lt;br /&gt;
The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV show information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique ID from the TV information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online TV show databases.&lt;br /&gt;
If &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; contains all the necessary info about the respective TV show in XML format then this actions may not pass any &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
In this case Kodi will use all the information parsed from the XML file and will not call &#039;&#039;&#039;getdetails&#039;&#039;&#039; action.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl (episode)==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is also called as for each episode .NFO file that is present in a TV show directory.&lt;br /&gt;
The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary episode info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to the episode page on a TV show information website or some unique ID to request episode information from a REST API.&lt;br /&gt;
&lt;br /&gt;
If an episode .NFO file contains all the necessary info about the respective episode in XML format then this action may not pass any &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
In this case Kodi will use all the information parsed from the XML file and will not call &#039;&#039;&#039;getepisodedetails&#039;&#039;&#039; action.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
One of the necessary properties that are set via &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt;. This should be some unique string that can be used to retrieve&lt;br /&gt;
the list of TV show episoded with all the necessary info.&lt;br /&gt;
&lt;br /&gt;
==getepisodelist==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodelist&amp;lt;/code&amp;gt; action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi&lt;br /&gt;
with information about available TV show episodes. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter that is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; property set by &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action.&lt;br /&gt;
A scraper needs to set &#039;&#039;&#039;url&#039;&#039;&#039; for each &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance that is some unique string that can be used to retrieve information about a specific episode.&lt;br /&gt;
&lt;br /&gt;
==getepisodedetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodedetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stage and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getartwork&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions or parsed form an XML &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; file if the scraper haven&#039;t set any. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your .NFO file contains the default unique ID that is different from the ID of the TV show database your scraper works with,&lt;br /&gt;
you must set the correct default unique ID in &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action. Otherwise &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; will receive the default unique ID from your .NFO file&lt;br /&gt;
and your scraper may not be able to find any artwork using this ID.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example TV Shows Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python TV show scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.tv metadata.demo.tv addon].&lt;br /&gt;
&lt;br /&gt;
[[Category:Scraper]]&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242289</id>
		<title>Python movie scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242289"/>
		<updated>2022-06-19T18:50:40Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
&lt;br /&gt;
A movie scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific movie by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a movie poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if an .NFO file is present along with a movie file. The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;&lt;br /&gt;
parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique ID from the movie information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online movie databases.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getartwork&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt;&lt;br /&gt;
and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your .NFO file contains the default unique ID that is different from the ID of the movie database your scraper works with,&lt;br /&gt;
you must set the correct default unique ID in &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action. Otherwise &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; will receive the default unique ID from your .NFO file&lt;br /&gt;
and your scraper may not be able to find any artwork using this ID.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example Movie Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python movie scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.movies metadata.demo.movie addon].&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=242288</id>
		<title>Python tv scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=242288"/>
		<updated>2022-06-19T18:50:17Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
&lt;br /&gt;
A TV shows scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific TV show by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a TV show poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; file is present in a TV show directory.&lt;br /&gt;
The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV show information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique ID from the TV information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online TV show databases.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
One of the necessary properties that are set via &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt;. This should be some unique string that can be used to retrieve&lt;br /&gt;
the list of TV show episoded with all the necessary info.&lt;br /&gt;
&lt;br /&gt;
==getepisodelist==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodelist&amp;lt;/code&amp;gt; action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi&lt;br /&gt;
with information about available TV show episodes. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter that is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; property set by &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action.&lt;br /&gt;
A scraper needs to set &#039;&#039;&#039;url&#039;&#039;&#039; for each &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance that is some unique string that can be used to retrieve information about a specific episode.&lt;br /&gt;
&lt;br /&gt;
==getepisodedetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodedetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stage and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getartwork&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt;&lt;br /&gt;
and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your .NFO file contains the default unique ID that is different from the ID of the TV show database your scraper works with,&lt;br /&gt;
you must set the correct default unique ID in &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action. Otherwise &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; will receive the default unique ID from your .NFO file&lt;br /&gt;
and your scraper may not be able to find any artwork using this ID.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example TV Shows Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python TV show scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.tv metadata.demo.tv addon].&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=242287</id>
		<title>Python tv scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_tv_scraper_development&amp;diff=242287"/>
		<updated>2022-06-19T07:14:02Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
{{Wiki_revamp}}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
&lt;br /&gt;
A TV shows scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific TV show by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a TV show poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if &amp;lt;code&amp;gt;tvshow.nfo&amp;lt;/code&amp;gt; file is present in a TV show directory.&lt;br /&gt;
The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary TV show info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a TV show page on a TV show information website or a some unique ID to request TV show information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique ID from the TV information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online TV show databases.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
One of the necessary properties that are set via &amp;lt;code&amp;gt;ListItem.setInfo&amp;lt;/code&amp;gt; method is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt;. This should be some unique string that can be used to retrieve&lt;br /&gt;
the list of TV show episoded with all the necessary info.&lt;br /&gt;
&lt;br /&gt;
==getepisodelist==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodelist&amp;lt;/code&amp;gt; action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi&lt;br /&gt;
with information about available TV show episodes. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter that is &amp;lt;code&amp;gt;episodeguide&amp;lt;/code&amp;gt; property set by &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action.&lt;br /&gt;
A scraper needs to set &#039;&#039;&#039;url&#039;&#039;&#039; for each &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance that is some unique string that can be used to retrieve information about a specific episode.&lt;br /&gt;
&lt;br /&gt;
==getepisodedetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getepisodedetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stage and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getartwork&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt;&lt;br /&gt;
and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your .NFO file contains the default unique ID that is different from the ID of the TV show database your scraper works with,&lt;br /&gt;
you must set the correct default unique ID in &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action. Otherwise &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; will receive the default unique ID from your .NFO file&lt;br /&gt;
and your scraper may not be able to find any artwork using this ID.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example TV Shows Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python TV show scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.tv metadata.demo.tv addon].&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242227</id>
		<title>Python movie scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242227"/>
		<updated>2022-06-08T07:44:14Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
{{Wiki_revamp}}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
&lt;br /&gt;
A movie scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific movie by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a movie poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if an .NFO file is present along with a movie file. The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;&lt;br /&gt;
parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique ID from the movie information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online movie databases.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getartwork&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt;&lt;br /&gt;
and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your .NFO file contains the default unique ID that is different from the ID of the movie database your scraper works with,&lt;br /&gt;
you must set the correct default unique ID in &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action. Otherwise &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; will receive the default unique ID from your .NFO file&lt;br /&gt;
and your scraper may not be able to find any artwork using this ID.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example Movie Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python movie scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.movies metadata.demo.movie addon].&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242216</id>
		<title>Python movie scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242216"/>
		<updated>2022-06-07T10:12:35Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: /* getartwork */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
{{Wiki_revamp}}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON and data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
&lt;br /&gt;
A movie scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific movie by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a movie poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if an .NFO file is present along with a movie file. The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;&lt;br /&gt;
parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique ID from the movie information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online movie databases.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getartwork&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt;&lt;br /&gt;
and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your .NFO file contains the default unique ID that is different from the ID of the movie database your scraper works with,&lt;br /&gt;
you must set the correct default unique ID in &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action. Otherwise &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; will receive the default unique ID from your .NFO file&lt;br /&gt;
and your scraper may not be able to find any artwork using this ID.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example Movie Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python movie scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.movies metadata.demo.movie addon].&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242215</id>
		<title>Python movie scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242215"/>
		<updated>2022-06-07T10:11:11Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: /* getdetails */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
{{Wiki_revamp}}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON and data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
&lt;br /&gt;
A movie scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific movie by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a movie poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if an .NFO file is present along with a movie file. The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;&lt;br /&gt;
parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique ID from the movie information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online movie databases.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and should set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible using appropriate methods.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt;&lt;br /&gt;
and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your .NFO file contains the default unique ID that is different from the ID of the movie database your scraper works with,&lt;br /&gt;
you must set the correct default unique ID in &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action. Otherwise &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; will receive the default unique ID from your .NFO file&lt;br /&gt;
and your scraper may not be able to find any artwork using this ID.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example Movie Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python movie scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.movies metadata.demo.movie addon].&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242214</id>
		<title>Python movie scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242214"/>
		<updated>2022-06-07T08:33:04Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
{{Wiki_revamp}}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON and data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
&lt;br /&gt;
A movie scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific movie by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a movie poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if an .NFO file is present along with a movie file. The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;&lt;br /&gt;
parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique ID from the movie information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online movie databases.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and must set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt;&lt;br /&gt;
and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your .NFO file contains the default unique ID that is different from the ID of the movie database your scraper works with,&lt;br /&gt;
you must set the correct default unique ID in &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action. Otherwise &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; will receive the default unique ID from your .NFO file&lt;br /&gt;
and your scraper may not be able to find any artwork using this ID.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example Movie Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python movie scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.movies metadata.demo.movie addon].&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242213</id>
		<title>Python movie scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242213"/>
		<updated>2022-06-07T08:32:26Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
{{Wiki_revamp}}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON and data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
&lt;br /&gt;
A movie scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific movie by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a movie poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if an .NFO file is present along with a movie file. The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;&lt;br /&gt;
parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique from the movie information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online movie databases.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and must set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt;&lt;br /&gt;
and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your .NFO file contains the default unique ID that is different from the ID of the movie database your scraper works with,&lt;br /&gt;
you must set the correct default unique ID in &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action. Otherwise &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; will receive the default unique ID from your .NFO file&lt;br /&gt;
and your scraper may not be able to find any artwork using this ID.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example Movie Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python movie scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.movies metadata.demo.movie addon].&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242212</id>
		<title>Python movie scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242212"/>
		<updated>2022-06-07T08:26:06Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
{{Wiki_revamp}}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON and data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
&lt;br /&gt;
A movie scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific movie by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a movie poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if an .NFO file is present along with a movie file. The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;&lt;br /&gt;
parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique from the movie information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online movie databases.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and must set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt;&lt;br /&gt;
and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example Movie Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python movie scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.movies metadata.demo.movie addon].&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242211</id>
		<title>Python movie scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242211"/>
		<updated>2022-06-07T08:25:05Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
{{Wiki_revamp}}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON and data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
An example of a URL query sting passed to a scraper plugin: &amp;lt;code&amp;gt;?action=getdetails&amp;amp;url=foo&amp;amp;pathSettings=%7B%22foo%22%3A+%22bar%22%7D&amp;lt;/code&amp;gt;.&lt;br /&gt;
Like other plugins, scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to the Kodi database instead of presenting lists of playable media items.&lt;br /&gt;
A movie scraper must support &amp;quot;action&amp;quot; calls that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific movie by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a movie poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if an .NFO file is present along with a movie file. The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;&lt;br /&gt;
parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique from the movie information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online movie databases.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and must set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt;&lt;br /&gt;
and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example Movie Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python movie scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.movies metadata.demo.movie addon].&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242210</id>
		<title>Python movie scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242210"/>
		<updated>2022-06-07T08:16:38Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
{{Wiki_revamp}}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON and data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
Scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to Kodi instead of presenting lists of playable media items. A movie scraper must support &amp;quot;action&amp;quot; calls&lt;br /&gt;
that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific movie by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a movie poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if an .NFO file is present along with a movie file. The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;&lt;br /&gt;
parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique from the movie information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online movie databases.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and must set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt;&lt;br /&gt;
and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
=Example Movie Scraper=&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python movie scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.movies metadata.demo.movie addon].&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242209</id>
		<title>Python movie scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242209"/>
		<updated>2022-06-07T08:16:02Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
{{Wiki_revamp}}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON and data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
Scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to Kodi instead of presenting lists of playable media items. A movie scraper must support &amp;quot;action&amp;quot; calls&lt;br /&gt;
that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific movie by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a movie poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if an .NFO file is present along with a movie file. The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;&lt;br /&gt;
parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Unique IDs&#039;&#039;&#039;: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique from the movie information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online movie databases.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and must set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt;&lt;br /&gt;
and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
==Example Movie Scraper==&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python movie scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.movies metadata.demo.movie addon].&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242208</id>
		<title>Python movie scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242208"/>
		<updated>2022-06-07T08:15:24Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
{{Wiki_revamp}}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON and data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
Scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to Kodi instead of presenting lists of playable media items. A movie scraper must support &amp;quot;action&amp;quot; calls&lt;br /&gt;
that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific movie by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a movie poster, for example.&lt;br /&gt;
&lt;br /&gt;
==NfoUrl==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NfoUrl&amp;lt;/code&amp;gt; action is called as an alternative to &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; if an .NFO file is present along with a movie file. The entire .NFO file contents are passed as &amp;lt;code&amp;gt;nfo&amp;lt;/code&amp;gt;&lt;br /&gt;
parameter. This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; to pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance to Kodi.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
* Unique IDs: set via &amp;lt;code&amp;gt;ListItem.setUniqueIDs()&amp;lt;/code&amp;gt; instance method. A scraper should set at least the default unique from the movie information site it works with.&lt;br /&gt;
Optionally it can set unique IDs from other online movie databases.&lt;br /&gt;
&lt;br /&gt;
==getdetails==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;url&#039;&#039;&#039; query parameter&lt;br /&gt;
from the previous stages and must set as much information to the &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instance as possible.&lt;br /&gt;
&lt;br /&gt;
==getartwork==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getdetails&amp;lt;/code&amp;gt; action must pass a single &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;xbmcplugin.setResolvedUrl()&amp;lt;/code&amp;gt; function. This action receives &#039;&#039;&#039;id&#039;&#039;&#039; query parameter&lt;br /&gt;
that is the default unique ID set by &#039;&#039;&#039;NfoUrl&#039;&#039;&#039; or &#039;&#039;&#039;getdetails&#039;&#039;&#039; actions. This action should set available artwork using &amp;lt;code&amp;gt;ListItem.addAvailableArtwork()&amp;lt;/code&amp;gt;&lt;br /&gt;
and &amp;lt;code&amp;gt;ListItem.setAvailableFanart()&amp;lt;/code&amp;gt; instance methods.&lt;br /&gt;
&lt;br /&gt;
=Path Settings=&lt;br /&gt;
&lt;br /&gt;
A scraper receives the current path settings via &amp;lt;code&amp;gt;pathSettings&amp;lt;/code&amp;gt; query parameters as a JSON-encoded string with each action call.&lt;br /&gt;
&lt;br /&gt;
==Example Movie Scraper==&lt;br /&gt;
&lt;br /&gt;
A very high-level example of a Python movie scraper can be found in the Kodi source code as [https://github.com/xbmc/xbmc/tree/master/addons/metadata.demo.movies metadata.demo.movie addon].&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242201</id>
		<title>Python movie scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242201"/>
		<updated>2022-06-06T13:23:40Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
{{Wiki_revamp}}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON and data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (media plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;br /&gt;
Scrapers are also interact with Kodi via the functions of &amp;lt;code&amp;gt;xbmcplugin&amp;lt;/code&amp;gt; Python API module and pass information to Kodi through &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances.&lt;br /&gt;
&lt;br /&gt;
Basically, a Python scraper is a media plugin that passes information to Kodi instead of presenting lists of playable media items. A movie scraper must support &amp;quot;action&amp;quot; calls&lt;br /&gt;
that are described below.&lt;br /&gt;
&lt;br /&gt;
=Actions=&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
The &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; action is used for searching for a specific movie by title and optionally a year that are passed as additional query parameters of the plugin call.&lt;br /&gt;
This action should use &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItem&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;xbmcplugin.addDirectoryItems&amp;lt;/code&amp;gt; to pass &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances to Kodi.&lt;br /&gt;
If only one instance is passed then it is considered as a perfect match. Otherwise the media file won&#039;t be matched and will need to be resolved manually by selecting&lt;br /&gt;
a necessary item from a list.&lt;br /&gt;
The &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; instances must be assigned the following properties:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;label&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt; parameter to the class constructor. This is the label that is presented to a user during scraping.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;url&#039;&#039;&#039;: passed as &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt; parameter to the class constructor. This should be some unique string that can be used to request all the necessary movie info from data provider&#039;s&lt;br /&gt;
website or API. It can be, for example, a link to a movie page on a movie information website or a some unique ID to request movie information from a REST API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;thumb&#039;&#039;&#039; (optional): passed via &amp;lt;code&amp;gt;setArtwork()&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;xbmcgui.ListItem&amp;lt;/code&amp;gt; class instance method. This should be a URL of a movie poster, for example.&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242103</id>
		<title>Python movie scraper development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Python_movie_scraper_development&amp;diff=242103"/>
		<updated>2022-05-25T07:41:23Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Scrapers]] {{l2|[[Development]]}} }}&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
Historically, Kodi has been supporting [https://kodi.wiki/view/HOW-TO:Write_media_scrapers XML scraping addons] that allow parsing online information sources&lt;br /&gt;
about movies, TV shows, music and so on. However, this approach has its limitations. First, XML parsing definitions with regular expressions are difficult to write and maintain.&lt;br /&gt;
Second, many information sources implemented REST APIs for getting information and regular expressions are not suitable for parsing JSON and data. That is why Python&lt;br /&gt;
scrapers have been introduced.&lt;br /&gt;
&lt;br /&gt;
Python scrapers are written in Python language and have similar structure to [https://kodi.wiki/view/HOW-TO:Video_addon media addons] (plugins).&lt;br /&gt;
They are also called by special &amp;lt;code&amp;gt;plugin://&amp;lt;/code&amp;gt; URLs with query parameters. The main query parameter is &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; that defines a scraping stage.&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Naming_video_files/Episodes&amp;diff=241560</id>
		<title>Naming video files/Episodes</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Naming_video_files/Episodes&amp;diff=241560"/>
		<updated>2022-02-18T21:53:29Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VideoLibraryCreate}}&lt;br /&gt;
{{mininav| [[Video library]] |[[HOW-TO:Create_Video_Library|Create Video Library]] }}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Be aware of the following:&lt;br /&gt;
&lt;br /&gt;
* The only item in the episode file name that the {{kodi}} scanner searches for is the Season and Episode numbering (&#039;&#039;SxxEyy&#039;&#039;). Everything else is irrelevant.&lt;br /&gt;
* It is this SxxEyy that is used to match and scrape the episode metadata and artwork.&lt;br /&gt;
* To reduce the risk of the scanner becoming confused by complicated naming, ensure your episode filenames are clean and simple as described below.&lt;br /&gt;
* Contrary to advice from 3rd party internet guides, you cannot set season and episode numbering through NFO Files.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Do not refer to IMDB for episode orders. There is no IMDB Scraper.&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;If you are using the default scraper then the site to check is [https://www.themoviedb.org/ TMDB]. If you have changed to [https://www.thetvdb.com/ TVDB] or [https://www.tvmaze.com/ TV Maze], check the appropriate site.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Single Episode Files =&lt;br /&gt;
Episode files are assumed to contain a single episode. If you have files that contain two or more episodes, then read the Multi-Episodes section below. &lt;br /&gt;
&lt;br /&gt;
The following table details the &#039;&#039;Minimum&#039;&#039; and &#039;&#039;Recommended&#039;&#039; naming for episodes files. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;prettytable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| scope=&amp;quot;row&amp;quot; colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align:center; background-color:#a1f5e4;&amp;quot; | &#039;&#039;&#039;Minimum required episode name:&#039;&#039;&#039; || ! scope=&amp;quot;row&amp;quot; colspan=&amp;quot;1&amp;quot;  style=&amp;quot;width:10px; background-color:#d3d3d5; text-align:center;&amp;quot;|  || scope=&amp;quot;row&amp;quot; colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align:center; background-color:#a1f5e4;&amp;quot; | &#039;&#039;&#039;Recommended episode name:&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; colspan=&amp;quot;2&amp;quot;  style=&amp;quot;width:400px; background-color:#f5f5a1; text-align:center;&amp;quot;|&#039;&#039;S01E01.mkv&#039;&#039;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; colspan=&amp;quot;1&amp;quot;  style=&amp;quot;width:10px; background-color:#d3d3d5; text-align:center;&amp;quot;| &lt;br /&gt;
! scope=&amp;quot;row&amp;quot; colspan=&amp;quot;2&amp;quot;  style=&amp;quot;width:400px; background-color:#f5f5a1; text-align:center;&amp;quot;| &#039;&#039;Angel (1999) S01E01.mkv&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Where:&lt;br /&gt;
|&#039;&#039;&#039;&#039;&#039;S01E01&#039;&#039;&#039;&#039;&#039; = Season 1, Episode 1 - no spaces || ! scope=&amp;quot;row&amp;quot; colspan=&amp;quot;1&amp;quot;  style=&amp;quot;width:10px; background-color:#d3d3d5; text-align:center;&amp;quot;| ||Where: ||&#039;&#039;&#039;&#039;&#039;Angel (1999)&#039;&#039;&#039;&#039;&#039; = TV Show name&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
| || ! scope=&amp;quot;row&amp;quot; colspan=&amp;quot;1&amp;quot;  style=&amp;quot;width:10px; background-color:#d3d3d5; text-align:center;&amp;quot;|  || || &#039;&#039;&#039;&#039;&#039;S01E01&#039;&#039;&#039;&#039;&#039; = Season 1, Episode 1 - no spaces&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The Pattern &#039;&#039;&#039;S01E01&#039;&#039;&#039; is the most accurate available. Other Patterns are available in the table below with the most accurate at the top and accuracy decreasing down the list.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{|class=&amp;quot;{{{1|prettytable}}}&amp;quot; style=&amp;quot;margin: 0.5em 2.0em 0.5em 0em; font-size: 0.80em; {{border-radius|5px}}; float: top; clear: top;&amp;quot; width=&amp;quot;500&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#;&amp;quot; | With Season&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#;&amp;quot; | No Season&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#;&amp;quot; | By Date&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#;&amp;quot; | By Title&lt;br /&gt;
|+&lt;br /&gt;
! style=&amp;quot;background-color:#;&amp;quot; | Order&lt;br /&gt;
! style=&amp;quot;background-color:#; width:200px&amp;quot; | Episode Naming&lt;br /&gt;
! style=&amp;quot;background-color:#;&amp;quot; | Order&lt;br /&gt;
! style=&amp;quot;background-color:#; width:200px&amp;quot; | Episode Naming&lt;br /&gt;
! style=&amp;quot;background-color:#;&amp;quot; | Order&lt;br /&gt;
! style=&amp;quot;background-color:#; width:200px&amp;quot; | Episode Naming&lt;br /&gt;
! style=&amp;quot;background-color:#;&amp;quot; | Order&lt;br /&gt;
! style=&amp;quot;background-color:#; width:200px&amp;quot; | Episode Naming&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|1&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&#039;&#039;Name&#039;&#039; &#039;&#039;&#039;S01E02&#039;&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|2&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&#039;&#039;Name&#039;&#039; &#039;&#039;&#039;ep02&#039;&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|3&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&#039;&#039;Name&#039;&#039; &#039;&#039;&#039;yyyy.mm.dd&#039;&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|7&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&#039;&#039;&#039;Name&#039;&#039;&#039;.&#039;&#039;special&#039;&#039;.ext&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|1&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&#039;&#039;Name&#039;&#039; &#039;&#039;&#039;S1E2&#039;&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|2&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&#039;&#039;Name&#039;&#039; &#039;&#039;&#039;ep_02&#039;&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|3&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&#039;&#039;Name&#039;&#039; &#039;&#039;&#039;yyyy-mm-dd&#039;&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|1&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&#039;&#039;Name&#039;&#039; &#039;&#039;&#039;S01.E02&#039;&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|7&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&#039;&#039;Name&#039;&#039; &#039;&#039;&#039;part.II&#039;&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|4&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&#039;&#039;Name&#039;&#039; &#039;&#039;&#039;dd.mm.yyyy&#039;&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|1&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&#039;&#039;Name&#039;&#039; &#039;&#039;&#039;S01_E02&#039;&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|7&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&#039;&#039;Name&#039;&#039; &#039;&#039;&#039;pt.II&#039;&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|1&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&#039;&#039;Name&#039;&#039; &#039;&#039;&#039;S01xE02&#039;&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|7&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&#039;&#039;Name&#039;&#039; &#039;&#039;&#039;pt_II&#039;&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|5&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&#039;&#039;Name&#039;&#039; &#039;&#039;&#039;1x02&#039;&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|6&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&#039;&#039;Name&#039;&#039; &#039;&#039;&#039;102&#039;&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:left;&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
;With Season&lt;br /&gt;
:The most commonly used for nearly all TV Shows.&lt;br /&gt;
;No Season&lt;br /&gt;
:Normally used for Anime or single season TV Shows. Not commonly used.&lt;br /&gt;
;By date&lt;br /&gt;
:Used for long-running daily shows. Check the scraper site for numbering method used.&lt;br /&gt;
;By title (added in v.20 &amp;quot;Nexus&amp;quot;)&lt;br /&gt;
:Used for special episodes in case if a data provider does not support &amp;quot;zero season&amp;quot; convention for specials, e.g. TVmaze. It allows to match special episodes by their titles.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Multi-Episode Files =&lt;br /&gt;
If you video files contain two or more episodes, then the following naming is required to scan multiple episodes from a single file.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;prettytable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| scope=&amp;quot;row&amp;quot; colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align:center; background-color:#a1f5e4;&amp;quot; | &#039;&#039;&#039;Minimum required episode name:&#039;&#039;&#039; || ! scope=&amp;quot;row&amp;quot; colspan=&amp;quot;1&amp;quot;  style=&amp;quot;width:10px; background-color:#d3d3d5; text-align:center;&amp;quot;|  || scope=&amp;quot;row&amp;quot; colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align:center; background-color:#a1f5e4;&amp;quot; | &#039;&#039;&#039;Recommended episode name:&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; colspan=&amp;quot;2&amp;quot;  style=&amp;quot;width:400px; background-color:#f5f5a1; text-align:center;&amp;quot;|&#039;&#039;S01E01E02E04.mkv&#039;&#039;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; colspan=&amp;quot;1&amp;quot;  style=&amp;quot;width:10px; background-color:#d3d3d5; text-align:center;&amp;quot;| &lt;br /&gt;
! scope=&amp;quot;row&amp;quot; colspan=&amp;quot;2&amp;quot;  style=&amp;quot;width:400px; background-color:#f5f5a1; text-align:center;&amp;quot;| &#039;&#039;Angel (1999) S01E01E02E04.mkv&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Where:&lt;br /&gt;
|&#039;&#039;&#039;&#039;&#039;S01E01E02E04&#039;&#039;&#039;&#039;&#039; = Season 1, Episode 1, 2 &amp;amp; 4 || ! scope=&amp;quot;row&amp;quot; colspan=&amp;quot;1&amp;quot;  style=&amp;quot;width:10px; background-color:#d3d3d5; text-align:center;&amp;quot;| ||Where: ||&#039;&#039;&#039;&#039;&#039;Angel (1999)&#039;&#039;&#039;&#039;&#039; = TV Show name&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
| &#039;&#039;Note that Episode 3 is not included&#039;&#039; || ! scope=&amp;quot;row&amp;quot; colspan=&amp;quot;1&amp;quot;  style=&amp;quot;width:10px; background-color:#d3d3d5; text-align:center;&amp;quot;|  || || &#039;&#039;&#039;&#039;&#039;S01E01E02E04&#039;&#039;&#039;&#039;&#039; = Season 1, Episode 1, 2 &amp;amp; 4&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{|class=&amp;quot;{{{1|prettytable}}}&amp;quot; style=&amp;quot;margin: 0.5em 2.0em 0.5em 0em; font-size: 0.80em; {{border-radius|5px}}; float: top; clear: top;&amp;quot; width=&amp;quot;500&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#;&amp;quot; | Complex Pattern&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#;&amp;quot; | Short Pattern&lt;br /&gt;
|+&lt;br /&gt;
! style=&amp;quot;background-color:#;&amp;quot; | Order&lt;br /&gt;
! style=&amp;quot;background-color:#; width:350px&amp;quot; | Example Name&lt;br /&gt;
! style=&amp;quot;background-color:#;&amp;quot; | Order&lt;br /&gt;
! style=&amp;quot;background-color:#; width:200px&amp;quot; | Example Name&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|1&lt;br /&gt;
|style=&amp;quot;width:300px; text-align:left;&amp;quot;|&#039;&#039;name&#039;&#039; &#039;&#039;&#039;s01e01&#039;&#039;&#039;-&#039;&#039;&#039;s01e02&#039;&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|1&lt;br /&gt;
|style=&amp;quot;width:150px; text-align:left;&amp;quot;|&#039;&#039;name&#039;&#039; &#039;&#039;&#039;s01e01e02&#039;&#039;&#039;.ext&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|1&lt;br /&gt;
|style=&amp;quot;width:300px; text-align:left;&amp;quot;|&#039;&#039;name&#039;&#039; &#039;&#039;&#039;s01e01&#039;&#039;&#039;-&#039;&#039;episode1.title&#039;&#039;-&#039;&#039;&#039;s01e02&#039;&#039;&#039;-&#039;&#039;episode2.title&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|1&lt;br /&gt;
|style=&amp;quot;width:150px; text-align:left;&amp;quot;|&#039;&#039;name&#039;&#039; &#039;&#039;&#039;s01e01-02-03&#039;&#039;&#039;.ext&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|1&lt;br /&gt;
|style=&amp;quot;width:300px; text-align:left;&amp;quot;|&#039;&#039;name&#039;&#039; &#039;&#039;&#039;s01e01&#039;&#039;&#039;-&#039;&#039;&#039;s01e02&#039;&#039;&#039;-&#039;&#039;&#039;s01e03&#039;&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|5&lt;br /&gt;
|style=&amp;quot;width:150px; text-align:left;&amp;quot;|&#039;&#039;name&#039;&#039; &#039;&#039;&#039;1x01x02&#039;&#039;&#039;.ext&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|5&lt;br /&gt;
|style=&amp;quot;width:300px; text-align:left;&amp;quot;|&#039;&#039;name&#039;&#039; &#039;&#039;&#039;1x01&#039;&#039;&#039;-&#039;&#039;&#039;1x02&#039;&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|2&lt;br /&gt;
|style=&amp;quot;width:150px; text-align:left;&amp;quot;|&#039;&#039;name&#039;&#039; &#039;&#039;&#039;ep01-02&#039;&#039;&#039;.ext&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|2&lt;br /&gt;
|style=&amp;quot;width:300px; text-align:left;&amp;quot;|&#039;&#039;name&#039;&#039; &#039;&#039;&#039;ep01&#039;&#039;&#039;-&#039;&#039;&#039;ep02&#039;&#039;&#039;.ext&lt;br /&gt;
|style=&amp;quot;width:50px; text-align:center;&amp;quot;|&lt;br /&gt;
|style=&amp;quot;width:150px; text-align:left;&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
&#039;&#039;&#039;It is recommended that multi-episode files be split into Single Episode files.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In cases where the video file contains more than one episode, you must nominate each episode in the filename. &lt;br /&gt;
&lt;br /&gt;
* The patterns are the same as Single Episode numbering, but extended to include multiple episodes.&lt;br /&gt;
* Only the episodes in the file name will be added, e.g. &#039;&#039;&#039;&#039;&#039;Angel (1999) S01E01E04.mkv&#039;&#039;&#039;&#039;&#039; will scrape episodes 1 and 4 but not include episodes 2 and 3.&lt;br /&gt;
* When using a single video file for multiple episodes it is possible to tell set episode bookmarks for each episode in the file. See: &#039;&#039;&#039;&#039;&#039;[[bookmarks|Episode Bookmarks]]&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&#039;&#039;See also: [[Advancedsettings.xml#tvmultipartmatching|Multi-Episode Matching]]&#039;&#039;&#039;&#039;&#039; to create additional pattern matches&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Episode Groups =&lt;br /&gt;
Episode Groups or Orders are listings with alternate episode orders. Some TV Shows are broadcast in one order but the DVD/Bluray release may have a different screening order. A well known example is the TV Show &#039;&#039;Firefly&#039;&#039; where the Studio opted to broadcast high action episodes for ratings first, while the Producer wanted a different order to correctly unfold the storyline.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== TheMovieDB-TV Shows ==&lt;br /&gt;
TheMovieDB uses Episode Groups for additional episode orders.&lt;br /&gt;
&lt;br /&gt;
To use one of the orders for scraping, follow the images below. Paste the address into a &#039;&#039;&#039;&#039;&#039;[[NFO_files/Parsing|Parsing NFO file]]&#039;&#039;&#039;&#039;&#039; then scrape. The Parsing NFO File will point the scraper to the listing. &amp;lt;ref&amp;gt;https://forum.kodi.tv/showthread.php?tid=338467&amp;amp;pid=2801494#pid2801494&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;traditional&amp;quot; widths=&amp;quot;500px&amp;quot; heights=&amp;quot;283px&amp;quot;&amp;gt;&lt;br /&gt;
File:EpisodeGroups01.jpg|Image 1- Accessing Episode Groups&lt;br /&gt;
File:EpisodeGroups02.jpg|Image 2- Available Episode Groups&lt;br /&gt;
File:EpisodeGroups03.jpg|Image 3- Select a Group, then copy the address for use in a &#039;&#039;&#039;&#039;&#039;[[NFO_files/Parsing|Parsing NFO file]]&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The TVDB ==&lt;br /&gt;
{{editor note|TVDB will shortly be updating to v4 API with major changes to episode orders. This is expected to occur &amp;lt;strike&amp;gt;April 2021; Oct 2021&amp;lt;/strike&amp;gt;  2&amp;lt;sup&amp;gt;nd&amp;lt;/sup&amp;gt; Qtr. 2022.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= References =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{| style=&amp;quot;border: 1px solid black;&amp;quot;&lt;br /&gt;
| scope=&amp;quot;row&amp;quot; rowspan=&amp;quot;2&amp;quot; style=&amp;quot; text-align:center;&amp;quot; | [[File:Mergefrom.gif|60px|link=Naming_video_files/Seasons]]&lt;br /&gt;
| style=&amp;quot;width:200px; text-align:center;&amp;quot; | &#039;&#039;&#039;Previous step&#039;&#039;&#039; &lt;br /&gt;
| style=&amp;quot;width:200px; text-align:center;&amp;quot; | &#039;&#039;&#039;Next step&#039;&#039;&#039; &lt;br /&gt;
| scope=&amp;quot;row&amp;quot; rowspan=&amp;quot;2&amp;quot; style=&amp;quot; text-align:center;&amp;quot; | [[File:Merge-arrow.gif|60px|link=Adding_video_sources]]&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;width:200px; text-align:center;&amp;quot; | &#039;&#039;&#039;[[Naming_video_files/Seasons|Seasons Setup]]&#039;&#039;&#039;&lt;br /&gt;
| style=&amp;quot;width:200px; text-align:center;&amp;quot; | &#039;&#039;&#039;[[Adding_video_sources|Add Source &amp;amp; Scrape]]&#039;&#039;&#039;&lt;br /&gt;
|}&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{top}}&lt;br /&gt;
{{updated|19}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Guides]]&lt;br /&gt;
[[Category:Karellen]]&lt;br /&gt;
[[Category:Video library]]&lt;br /&gt;
[[Category:First time user]]&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=HOW-TO:Video_addon&amp;diff=225492</id>
		<title>HOW-TO:Video addon</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=HOW-TO:Video_addon&amp;diff=225492"/>
		<updated>2021-05-14T08:55:43Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Development]]|[[Add-on development]]|[[Python development]]}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This tutorial will explain how to write your first Kodi/XBMC video plugin Add-on&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Tools=&lt;br /&gt;
Assuming you have already followed the Hello World Add-on you will have a text editor already setup. Since we are dealing with videos this time its probably a good idea to have a video player setup. We recommend another great open source project for this&lt;br /&gt;
&lt;br /&gt;
- VLC http://www.videolan.org/vlc/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Installing=&lt;br /&gt;
For this example we will use 2 nice basic video Add-on tutorials You can find the source-code here:&lt;br /&gt;
&lt;br /&gt;
https://github.com/romanvm/plugin.video.example&lt;br /&gt;
&lt;br /&gt;
You can either download as a zip and install both of these inside the kodi GUI from the install from zip feature. Or extract the zip into your userdata/add-ons folder.&lt;br /&gt;
&lt;br /&gt;
=Testing=&lt;br /&gt;
You can first give the add-on a test run by going to:&lt;br /&gt;
System &amp;gt;&amp;gt; Add-Ons &amp;gt;&amp;gt; Enabled Add-Ons &amp;gt;&amp;gt; Video Add-Ons &amp;gt;&amp;gt; Example Kodi video Plugin. You should now be able to watch some test videos hosted from an internet web server.&lt;br /&gt;
&lt;br /&gt;
[[File:Videotutorial1.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Explanation=&lt;br /&gt;
So whats happening in this add-on?&lt;br /&gt;
&lt;br /&gt;
Basically the Add-on is checking a website for the hosted videos. In this example we are directly linking to the videos, but there are possibilities for dynamic content and scraping of just about any online source&lt;br /&gt;
&lt;br /&gt;
Once the video link is sent to Kodi, our video player takes over and buffers, then plays the video just like any other media.&lt;br /&gt;
&lt;br /&gt;
=Structure=&lt;br /&gt;
main.py &amp;lt;-- This is the actual python code for your Add-On&lt;br /&gt;
&lt;br /&gt;
addon.xml &amp;lt;-- This is the Add-Ons metadata&lt;br /&gt;
&lt;br /&gt;
icon.png &amp;lt;-- A PNG icon for the add-on. It can be 256x256 or 512x512 pixels big. Try to make it look nice!&lt;br /&gt;
&lt;br /&gt;
Readme.md &amp;lt;-- The readme text file with a description of the Add-on and install instructions. This shows on the front of the GitHub page and helps users to understand your Add-on before downloading.&lt;br /&gt;
&lt;br /&gt;
=The Code=&lt;br /&gt;
So now we come to the actual Add-On code, this is where most of your Add-on is written and is a simple text file containing python code.&lt;br /&gt;
&lt;br /&gt;
First we initialize the Add-on and import and bits we need&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
     import sys&lt;br /&gt;
     from urllib.parse import parse_qsl&lt;br /&gt;
     import xbmcgui&lt;br /&gt;
     import xbmcplugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we do something else...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
     # Get the plugin url in plugin:// notation.&lt;br /&gt;
     __url__ = sys.argv[0]&lt;br /&gt;
     # Get the plugin handle as an integer number.&lt;br /&gt;
     __handle__ = int(sys.argv[1])&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we use a fixed set of properties simply for demonstrating purposes. In a &amp;quot;real life&amp;quot; plugin you will need to get info and links to video files/streams from some web-site or online service.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
VIDEOS = {&#039;Animals&#039;: [{&#039;name&#039;: &#039;Crab&#039;,&lt;br /&gt;
                       &#039;thumb&#039;: &#039;http://www.vidsplay.com/vids/crab.jpg&#039;,&lt;br /&gt;
                       &#039;video&#039;: &#039;http://www.vidsplay.com/vids/crab.mp4&#039;,&lt;br /&gt;
                       &#039;genre&#039;: &#039;Animals&#039;},&lt;br /&gt;
                      {&#039;name&#039;: &#039;Alligator&#039;,&lt;br /&gt;
                       &#039;thumb&#039;: &#039;http://www.vidsplay.com/vids/alligator.jpg&#039;,&lt;br /&gt;
                       &#039;video&#039;: &#039;http://www.vidsplay.com/vids/alligator.mp4&#039;,&lt;br /&gt;
                       &#039;genre&#039;: &#039;Animals&#039;},&lt;br /&gt;
                      {&#039;name&#039;: &#039;Turtle&#039;,&lt;br /&gt;
                       &#039;thumb&#039;: &#039;http://www.vidsplay.com/vids/turtle.jpg&#039;,&lt;br /&gt;
                       &#039;video&#039;: &#039;http://www.vidsplay.com/vids/turtle.mp4&#039;,&lt;br /&gt;
                       &#039;genre&#039;: &#039;Animals&#039;}&lt;br /&gt;
                      ],&lt;br /&gt;
            &#039;Cars&#039;: [{&#039;name&#039;: &#039;Postal Truck&#039;,&lt;br /&gt;
                      &#039;thumb&#039;: &#039;http://www.vidsplay.com/vids/us_postal.jpg&#039;,&lt;br /&gt;
                      &#039;video&#039;: &#039;http://www.vidsplay.com/vids/us_postal.mp4&#039;,&lt;br /&gt;
                      &#039;genre&#039;: &#039;Cars&#039;},&lt;br /&gt;
                     {&#039;name&#039;: &#039;Traffic&#039;,&lt;br /&gt;
                      &#039;thumb&#039;: &#039;http://www.vidsplay.com/vids/traffic1.jpg&#039;,&lt;br /&gt;
                      &#039;video&#039;: &#039;http://www.vidsplay.com/vids/traffic1.avi&#039;,&lt;br /&gt;
                      &#039;genre&#039;: &#039;Cars&#039;},&lt;br /&gt;
                     {&#039;name&#039;: &#039;Traffic Arrows&#039;,&lt;br /&gt;
                      &#039;thumb&#039;: &#039;http://www.vidsplay.com/vids/traffic_arrows.jpg&#039;,&lt;br /&gt;
                      &#039;video&#039;: &#039;http://www.vidsplay.com/vids/traffic_arrows.mp4&#039;,&lt;br /&gt;
                      &#039;genre&#039;: &#039;Cars&#039;}&lt;br /&gt;
                     ],&lt;br /&gt;
            &#039;Food&#039;: [{&#039;name&#039;: &#039;Chicken&#039;,&lt;br /&gt;
                      &#039;thumb&#039;: &#039;http://www.vidsplay.com/vids/chicken.jpg&#039;,&lt;br /&gt;
                      &#039;video&#039;: &#039;http://www.vidsplay.com/vids/bbqchicken.mp4&#039;,&lt;br /&gt;
                      &#039;genre&#039;: &#039;Food&#039;},&lt;br /&gt;
                     {&#039;name&#039;: &#039;Hamburger&#039;,&lt;br /&gt;
                      &#039;thumb&#039;: &#039;http://www.vidsplay.com/vids/hamburger.jpg&#039;,&lt;br /&gt;
                      &#039;video&#039;: &#039;http://www.vidsplay.com/vids/hamburger.mp4&#039;,&lt;br /&gt;
                      &#039;genre&#039;: &#039;Food&#039;},&lt;br /&gt;
                     {&#039;name&#039;: &#039;Pizza&#039;,&lt;br /&gt;
                      &#039;thumb&#039;: &#039;http://www.vidsplay.com/vids/pizza.jpg&#039;,&lt;br /&gt;
                      &#039;video&#039;: &#039;http://www.vidsplay.com/vids/pizza.mp4&#039;,&lt;br /&gt;
                      &#039;genre&#039;: &#039;Food&#039;}&lt;br /&gt;
                     ]}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
And now we define something else...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
def get_categories():&lt;br /&gt;
         &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
         Get the list of video categories.&lt;br /&gt;
         Here you can insert some parsing code that retrieves&lt;br /&gt;
         the list of video categories (e.g. &#039;Movies&#039;, &#039;TV-shows&#039;, &#039;Documentaries&#039; etc.)&lt;br /&gt;
         from some site or server.&lt;br /&gt;
         :return: list&lt;br /&gt;
         &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
         return VIDEOS.keys()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
And now we define something else...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
def get_videos(category):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Get the list of videofiles/streams.&lt;br /&gt;
    Here you can insert some parsing code that retrieves&lt;br /&gt;
    the list of videostreams in a given category from some site or server.&lt;br /&gt;
    :param category: str&lt;br /&gt;
    :return: list&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    return VIDEOS[category]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
And now we define the list of categories&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
def list_categories():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Create the list of video categories in the Kodi interface.&lt;br /&gt;
    :return: None&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Get video categories&lt;br /&gt;
    categories = get_categories()&lt;br /&gt;
    # Create a list for our items.&lt;br /&gt;
    listing = []&lt;br /&gt;
    # Iterate through categories&lt;br /&gt;
    for category in categories:&lt;br /&gt;
        # Create a list item with a text label and a thumbnail image.&lt;br /&gt;
        list_item = xbmcgui.ListItem(label=category, thumbnailImage=VIDEOS[category][0][&#039;thumb&#039;])&lt;br /&gt;
        # Set a fanart image for the list item.&lt;br /&gt;
        # Here we use the same image as the thumbnail for simplicity&#039;s sake.&lt;br /&gt;
        list_item.setProperty(&#039;fanart_image&#039;, VIDEOS[category][0][&#039;thumb&#039;])&lt;br /&gt;
        # Set additional info for the list item.&lt;br /&gt;
        # Here we use a category name for both properties for for simplicity&#039;s sake.&lt;br /&gt;
        # setInfo allows to set various information for an item.&lt;br /&gt;
        # For available properties see the following link:&lt;br /&gt;
        # http://mirrors.xbmc.org/docs/python-docs/15.x-isengard/xbmcgui.html#ListItem-setInfo&lt;br /&gt;
        list_item.setInfo(&#039;video&#039;, {&#039;title&#039;: category, &#039;genre&#039;: category})&lt;br /&gt;
        # Create a URL for the plugin recursive callback.&lt;br /&gt;
        # Example: plugin://plugin.video.example/?action=listing&amp;amp;category=Animals&lt;br /&gt;
        url = &#039;{0}?action=listing&amp;amp;category={1}&#039;.format(__url__, category)&lt;br /&gt;
        # is_folder = True means that this item opens a sub-list of lower level items.&lt;br /&gt;
        is_folder = True&lt;br /&gt;
        # Add our item to the listing as a 3-element tuple.&lt;br /&gt;
        listing.append((url, list_item, is_folder))&lt;br /&gt;
    # Add our listing to Kodi.&lt;br /&gt;
    # Large lists and/or slower systems benefit from adding all items at once via addDirectoryItems&lt;br /&gt;
    # instead of adding one by ove via addDirectoryItem.&lt;br /&gt;
    xbmcplugin.addDirectoryItems(__handle__, listing, len(listing))&lt;br /&gt;
    # Add a sort method for the virtual folder items (alphabetically, ignore articles)&lt;br /&gt;
    xbmcplugin.addSortMethod(__handle__, xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE)&lt;br /&gt;
    # Finish creating a virtual folder.&lt;br /&gt;
    xbmcplugin.endOfDirectory(__handle__)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And here we list the videos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
def list_videos(category):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Create the list of playable videos in the Kodi interface.&lt;br /&gt;
    :param category: str&lt;br /&gt;
    :return: None&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Get the list of videos in the category.&lt;br /&gt;
    videos = get_videos(category)&lt;br /&gt;
    # Create a list for our items.&lt;br /&gt;
    listing = []&lt;br /&gt;
    # Iterate through videos.&lt;br /&gt;
    for video in videos:&lt;br /&gt;
        # Create a list item with a text label and a thumbnail image.&lt;br /&gt;
        list_item = xbmcgui.ListItem(label=video[&#039;name&#039;], thumbnailImage=video[&#039;thumb&#039;])&lt;br /&gt;
        # Set a fanart image for the list item.&lt;br /&gt;
        # Here we use the same image as the thumbnail for simplicity&#039;s sake.&lt;br /&gt;
        list_item.setProperty(&#039;fanart_image&#039;, video[&#039;thumb&#039;])&lt;br /&gt;
        # Set additional info for the list item.&lt;br /&gt;
        list_item.setInfo(&#039;video&#039;, {&#039;title&#039;: video[&#039;name&#039;], &#039;genre&#039;: video[&#039;genre&#039;]})&lt;br /&gt;
        # Set &#039;IsPlayable&#039; property to &#039;true&#039;.&lt;br /&gt;
        # This is mandatory for playable items!&lt;br /&gt;
        list_item.setProperty(&#039;IsPlayable&#039;, &#039;true&#039;)&lt;br /&gt;
        # Create a URL for the plugin recursive callback.&lt;br /&gt;
        # Example: plugin://plugin.video.example/?action=play&amp;amp;video=http://www.vidsplay.com/vids/crab.mp4&lt;br /&gt;
        url = &#039;{0}?action=play&amp;amp;video={1}&#039;.format(__url__, video[&#039;video&#039;])&lt;br /&gt;
        # Add the list item to a virtual Kodi folder.&lt;br /&gt;
        # is_folder = False means that this item won&#039;t open any sub-list.&lt;br /&gt;
        is_folder = False&lt;br /&gt;
        # Add our item to the listing as a 3-element tuple.&lt;br /&gt;
        listing.append((url, list_item, is_folder))&lt;br /&gt;
    # Add our listing to Kodi.&lt;br /&gt;
    # Large lists and/or slower systems benefit from adding all items at once via addDirectoryItems&lt;br /&gt;
    # instead of adding one by ove via addDirectoryItem.&lt;br /&gt;
    xbmcplugin.addDirectoryItems(__handle__, listing, len(listing))&lt;br /&gt;
    # Add a sort method for the virtual folder items (alphabetically, ignore articles)&lt;br /&gt;
    xbmcplugin.addSortMethod(__handle__, xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE)&lt;br /&gt;
    # Finish creating a virtual folder.&lt;br /&gt;
    xbmcplugin.endOfDirectory(__handle__)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we tell Kodi how to find the video path to play the videos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
def play_video(path):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Play a video by the provided path.&lt;br /&gt;
    :param path: str&lt;br /&gt;
    :return: None&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Create a playable item with a path to play.&lt;br /&gt;
    play_item = xbmcgui.ListItem(path=path)&lt;br /&gt;
    # Pass the item to the Kodi player.&lt;br /&gt;
    xbmcplugin.setResolvedUrl(__handle__, True, listitem=play_item)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the router function&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
def router(paramstring):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Router function that calls other functions&lt;br /&gt;
    depending on the provided paramstring&lt;br /&gt;
    :param paramstring:&lt;br /&gt;
    :return:&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Parse a URL-encoded paramstring to the dictionary of&lt;br /&gt;
    # {&amp;lt;parameter&amp;gt;: &amp;lt;value&amp;gt;} elements&lt;br /&gt;
    params = dict(parse_qsl(paramstring[1:]))&lt;br /&gt;
    # Check the parameters passed to the plugin&lt;br /&gt;
    if params:&lt;br /&gt;
        if params[&#039;action&#039;] == &#039;listing&#039;:&lt;br /&gt;
            # Display the list of videos in a provided category.&lt;br /&gt;
            list_videos(params[&#039;category&#039;])&lt;br /&gt;
        elif params[&#039;action&#039;] == &#039;play&#039;:&lt;br /&gt;
            # Play a video from a provided URL.&lt;br /&gt;
            play_video(params[&#039;video&#039;])&lt;br /&gt;
    else:&lt;br /&gt;
        # If the plugin is called from Kodi UI without any parameters,&lt;br /&gt;
        # display the list of video categories&lt;br /&gt;
        list_categories()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Call the router function&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
if __name__ == &#039;__main__&#039;:&lt;br /&gt;
    # Call the router function and pass the plugin call parameters to it.&lt;br /&gt;
    router(sys.argv[2])&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Changing the code=&lt;br /&gt;
&lt;br /&gt;
Hopefully by now you have managed to run the Add-On, understand the structure and can see what the code can do. Now lets trying changing it a little!&lt;br /&gt;
&lt;br /&gt;
Since we already have the Add-on installed we can go directly to the Kodi userdata folder and edit the python directly. You can also have Kodi open at this time ready to run the Add-on when required. Just switch between your text editor and Kodi any time.&lt;br /&gt;
&lt;br /&gt;
Now open up the main.py file from your userdata folder and lets change what the text says.&lt;br /&gt;
&lt;br /&gt;
                 &#039;Cars&#039;: [{&#039;name&#039;: &#039;Postal Truck&#039;,&lt;br /&gt;
                      &#039;thumb&#039;: &#039;http://www.vidsplay.com/vids/us_postal.jpg&#039;,&lt;br /&gt;
                      &#039;video&#039;: &#039;http://www.vidsplay.com/vids/us_postal.mp4&#039;,&lt;br /&gt;
                      &#039;genre&#039;: &#039;Cars&#039;},&lt;br /&gt;
&lt;br /&gt;
Try changing some of the links to another jpeg file or hosted online video. Also try to change the genre and see how that effects the view in Kodi.&lt;br /&gt;
&lt;br /&gt;
Click save on your text editor and now try running the Add-On inside Kodi. You should see the new video links and navigation right away.&lt;br /&gt;
&lt;br /&gt;
Congratulations! you&#039;ve just played an online video from your very own Video Add-on&lt;br /&gt;
&lt;br /&gt;
=Streaming Video=&lt;br /&gt;
In addition to this guide, here are some comments from an experienced developer who has worked with streaming video sites:&lt;br /&gt;
&lt;br /&gt;
The docs on codedocs.xyz will help you a lot, way more than any wiki.&lt;br /&gt;
&lt;br /&gt;
https://codedocs.xyz/xbmc/xbmc/&lt;br /&gt;
&lt;br /&gt;
Speaking of docs, the ListItem reference will be most useful, time and time again.&lt;br /&gt;
&lt;br /&gt;
https://codedocs.xyz/xbmc/xbmc/group__python__xbmcgui__listitem.html#gac31a08def90f50295146753353cb9541&lt;br /&gt;
&lt;br /&gt;
Since you&#039;re relying on a streaming platform you won&#039;t need to do anything particular yourself, you can get away with fetching the data and posting an item with the URL of the video. InputStream.Adaptive configuration might be needed, especially if the videos need DRM.&lt;br /&gt;
&lt;br /&gt;
You can get a lot done with the requests module, depending on the data you&#039;re processing. It&#039;s fully supported in Kodi, cookie and sessions included.&lt;br /&gt;
In short, it&#039;s really simple, you:&lt;br /&gt;
&lt;br /&gt;
- get the information you need off the internet (title/URL could suffice for a start);&lt;br /&gt;
&lt;br /&gt;
- you generate items that Kodi will treat as video sources (see xbmcplugin.addDirectoryItem() and xbmcgui.ListItem());&lt;br /&gt;
&lt;br /&gt;
You could also read the sources of plugins such as AsciiDisco&#039;s Netflix or Sandmann79&#039;s Amazon/AmazonVOD addons.&lt;br /&gt;
&lt;br /&gt;
You can read more in this thread&lt;br /&gt;
https://forum.kodi.tv/showthread.php?tid=348328&lt;br /&gt;
&lt;br /&gt;
=Final Thoughts=&lt;br /&gt;
&lt;br /&gt;
Writing a Video Add-on is actually pretty simple once you get the basic structure correct. You can scrape most online sources with Regex, or host your own videos on the web. You can also play youtube clips or vevo videos using some additional easy to use modules.&lt;br /&gt;
&lt;br /&gt;
If you have any questions about this tutorial, feel free to discuss it on our forums here: http://forum.kodi.tv/showthread.php?tid=248774&lt;br /&gt;
&lt;br /&gt;
=Extra info=&lt;br /&gt;
&lt;br /&gt;
Just a reminder...&lt;br /&gt;
IMPORTANT!!!!!!!   Do not mix tabs and spaces in python&lt;br /&gt;
&lt;br /&gt;
[[Category:Add-on development]]&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Add-on_development&amp;diff=225491</id>
		<title>Add-on development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Add-on_development&amp;diff=225491"/>
		<updated>2021-05-14T08:53:12Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Development]]}}&lt;br /&gt;
[[File:Wiki logo.png|150px|link=|left]]&lt;br /&gt;
&amp;lt;section begin=&amp;quot;intro&amp;quot; /&amp;gt;This area contains information, tutorials, and links for creating add-ons (and plug-ins) for Kodi.&amp;lt;section end=&amp;quot;intro&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{-}}&lt;br /&gt;
----&lt;br /&gt;
{{huge|&#039;&#039;&#039;{{color|black|General}}&#039;&#039;&#039;}}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| width=&amp;quot;16%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Nuvola apps kthememgr.png|link=About Add-ons}}&lt;br /&gt;
| width=&amp;quot;17%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Administration.png|link=Add-on settings}}&lt;br /&gt;
| width=&amp;quot;16%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Applications-development.png|link=Add-on structure|title=Add-on Structure}}&lt;br /&gt;
| width=&amp;quot;17%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Tool-box-icon.png|link=Development Tools}}&lt;br /&gt;
| width=&amp;quot;16%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=60.jpg|link=Special protocol}}&lt;br /&gt;
| width=&amp;quot;18%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Translate icon.jpg|link=Translation System}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
{{huge|&#039;&#039;&#039;{{color|black|Add-on Types}}&#039;&#039;&#039;}}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| width=&amp;quot;14%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Nuvola apps kthememgr.png|link=Plugin sources}}&lt;br /&gt;
| width=&amp;quot;14%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Misc-Misc-Box-icon.png|link=Add-on_repositories|title=Repository add-ons}}&lt;br /&gt;
| width=&amp;quot;14%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Web-icon.png|link=HOW-TO:Write media scrapers|title=Scraper add-ons}}&lt;br /&gt;
| width=&amp;quot;14%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Applications-development.png|link=Script sources|title=Scripts}}&lt;br /&gt;
| width=&amp;quot;14%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Administration.png|link=Script subtitles}}&lt;br /&gt;
| width=&amp;quot;14%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Gnome-system-run.png|link=Service add-ons}}&lt;br /&gt;
| width=&amp;quot;14%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Weather_addon.png|link=Weather addons}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
{{huge|&#039;&#039;&#039;{{color|black|Tutorials}}&#039;&#039;&#039;}}&lt;br /&gt;
&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| width=&amp;quot;12.5%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=music-icon.png|link=HOW-TO:Audio_addon|title=Audio Tutorial}}&lt;br /&gt;
| width=&amp;quot;12.5%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=context-menu-icon.png|link=Context_Item_Add-ons|title=Context Item Tutorial}}&lt;br /&gt;
| width=&amp;quot;12.5%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Addons-icon.png|link=Audio-video_add-on_tutorial|title=General Add-on Tutorial}}&lt;br /&gt;
| width=&amp;quot;12.5%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Translation - Noun project 987.png|link=HOW-TO:HelloWorld_addon|title=Hello World Tutorial}}&lt;br /&gt;
| width=&amp;quot;12.5%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Screensaver-icon.png|link=HOW-TO:Screensaver_addon|title=Screensaver Tutorial}}&lt;br /&gt;
| width=&amp;quot;12.5%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=script-icon.png|link=HOW-TO:Script_addon|title=Script Tutorial}}&lt;br /&gt;
| width=&amp;quot;12.5%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Visualisation-icon.jpg|link=HOW-TO:Visualisation_addon|title=Visualisation Tutorial}}&lt;br /&gt;
| width=&amp;quot;12.5%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=video-icon.png|link=HOW-TO:Video_addon|title=Video Addon Tutorial}}&lt;br /&gt;
|}&lt;br /&gt;
----&lt;br /&gt;
{{huge|&#039;&#039;&#039;{{color|black|Advanced}}&#039;&#039;&#039;}}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| width=&amp;quot;12.5%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Unicode icon.jpg|link=Add-on unicode paths}}&lt;br /&gt;
| width=&amp;quot;12.5%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=501159.png‎‎|link=JSON-RPC API}}&lt;br /&gt;
| width=&amp;quot;12.5%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Book icon 1.png|link=Python_libraries|title=Kodi Python Libraries}}&lt;br /&gt;
| width=&amp;quot;12.5%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Boolean_operation_icon.jpg‎|link=List of boolean conditions}}&lt;br /&gt;
| width=&amp;quot;12.5%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Apps-Brackets-B-icon.png‎|link=List of built-in functions}}&lt;br /&gt;
| width=&amp;quot;12.5%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=shopping-list-generator-icon.png‎|link=InfoLabels|title=List of info labels}}&lt;br /&gt;
| width=&amp;quot;12.5%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Web-pdb-icon.png‎|link=Python_debugging|title=Python Debugging}}&lt;br /&gt;
| width=&amp;quot;12.5%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Windowsicon.png‎‎|link=Window IDs|title=Window IDs}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
{{huge|&#039;&#039;&#039;{{color|black|Publishing}}&#039;&#039;&#039;}}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| width=&amp;quot;25%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Thumbs up font awesome.png‎|link=Add-on rules}}&lt;br /&gt;
| width=&amp;quot;25%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Upload-128.png|link=Submitting Add-ons}}&lt;br /&gt;
| width=&amp;quot;25%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Thumbnail-symbol-transparent.png|link=Official_add-on_repository|title=Official Add-on Repository}}&lt;br /&gt;
| width=&amp;quot;25%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Box_icon.png‎|link=Unofficial add-on repositories|title=Third-party Add-on Repositories}}&lt;br /&gt;
|}&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Add-on development|*]]&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=HOW-TO:Debug_Python_Scripts_with_Web-PDB&amp;diff=141466</id>
		<title>HOW-TO:Debug Python Scripts with Web-PDB</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=HOW-TO:Debug_Python_Scripts_with_Web-PDB&amp;diff=141466"/>
		<updated>2018-10-13T20:38:05Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Development]]|[[Add-on development]]|[[Python development]]}}&lt;br /&gt;
&lt;br /&gt;
[https://github.com/romanvm/kodi.web-pdb Web-PDB] is a remote web-interface to Python&#039;s built-in [https://docs.python.org/2/library/pdb.html PDB] debugger with additional convenience features. It is not tied to any IDE or other software, all you need is a common web-browser, e.g. Chrome or Firefox. Web-PDB is compatible with both Python 2 and 3, so you can use it to debug your Python 3 compatible addons.&lt;br /&gt;
&lt;br /&gt;
[[File:web-pdb.png]]&lt;br /&gt;
&lt;br /&gt;
Web-PDB for Kodi is available as an addon in the official Kodi addons repo.&lt;br /&gt;
&lt;br /&gt;
== How To Use Web-PDB for Kodi ==&lt;br /&gt;
&lt;br /&gt;
1. Install Web-PDB addon: &#039;&#039;&#039;Kodi Add-on repository &amp;gt; Program add-ons &amp;gt; Web-PDB&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
2. Add &amp;lt;code&amp;gt;script.module.web-pdb&amp;lt;/code&amp;gt; to [[addon.xml]] as a dependency:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;requires&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
   &amp;lt;import addon=&amp;quot;script.module.web-pdb&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;requires&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. Restart Kodi so that it re-reads addon dependencies.&lt;br /&gt;
&lt;br /&gt;
4. Insert the following line into your addon code at the point where you want to start debugging:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
import web_pdb; web_pdb.set_trace()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;set_trace()&amp;lt;/code&amp;gt; call will suspend your addon and open a web-UI at the default port 5555 (port value can be changed). At the same time a notification will be displayed in Kodi, indicating that a debug session is active. The notification also shows web-UI host/port.&lt;br /&gt;
&lt;br /&gt;
5. Enter in your the address bar of your browser: &amp;lt;code&amp;gt;http://&amp;lt;your Kodi machine hostname or IP&amp;gt;:5555&amp;lt;/code&amp;gt;, for example &amp;lt;code&amp;gt;http://monty-python:5555&amp;lt;/code&amp;gt;. Use &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt; as a hostname if you are connecting from the same machine that runs Kodi. If everything is OK, you should see the Web-PDB UI. Now you can use all PDB commands and features. Additional &#039;&#039;&#039;Current file&#039;&#039;&#039;, &#039;&#039;&#039;Globals&#039;&#039;&#039; and &#039;&#039;&#039;Locals&#039;&#039;&#039; information boxes help you better track your program runtime state.&lt;br /&gt;
&lt;br /&gt;
== More Information ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/romanvm/kodi.web-pdb Web-PDB for Kodi on GitHub].&lt;br /&gt;
* [https://docs.python.org/2/library/pdb.html PDB debugger documentation].&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=HOW-TO:Debug_Python_Scripts_with_Web-PDB&amp;diff=141465</id>
		<title>HOW-TO:Debug Python Scripts with Web-PDB</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=HOW-TO:Debug_Python_Scripts_with_Web-PDB&amp;diff=141465"/>
		<updated>2018-10-13T20:32:17Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: Add mininav&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Development]]|[[Add-on development]]|[[Python development]]}}&lt;br /&gt;
&lt;br /&gt;
[https://github.com/romanvm/kodi.web-pdb Web-PDB] is a remote web-interface to Python&#039;s built-in [https://docs.python.org/2/library/pdb.html PDB] debugger with additional convenience features. It is not tied to any IDE or other software, all you need is a common web-browser, e.g. Chrome or Firefox.&lt;br /&gt;
[[File:web-pdb.png]]&lt;br /&gt;
&lt;br /&gt;
Web-PDB for Kodi is available as an addon in the official Kodi addons repo.&lt;br /&gt;
&lt;br /&gt;
== How To Use Web-PDB for Kodi ==&lt;br /&gt;
&lt;br /&gt;
1. Install Web-PDB addon: &#039;&#039;&#039;Kodi Add-on repository &amp;gt; Program add-ons &amp;gt; Web-PDB&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
2. Add &amp;lt;code&amp;gt;script.module.web-pdb&amp;lt;/code&amp;gt; to [[addon.xml]] as a dependency:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;requires&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
   &amp;lt;import addon=&amp;quot;script.module.web-pdb&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;requires&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. Restart Kodi so that it re-reads addon dependencies.&lt;br /&gt;
&lt;br /&gt;
4. Insert the following line into your addon code at the point where you want to start debugging:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
import web_pdb; web_pdb.set_trace()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;set_trace()&amp;lt;/code&amp;gt; call will suspend your addon and open a web-UI at the default port 5555 (port value can be changed). At the same time a notification will be displayed in Kodi, indicating that a debug session is active. The notification also shows web-UI host/port.&lt;br /&gt;
&lt;br /&gt;
5. Enter in your the address bar of your browser: &amp;lt;code&amp;gt;http://&amp;lt;your Kodi machine hostname or IP&amp;gt;:5555&amp;lt;/code&amp;gt;, for example &amp;lt;code&amp;gt;http://monty-python:5555&amp;lt;/code&amp;gt;. Use &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt; as a hostname if you are connecting from the same machine that runs Kodi. If everything is OK, you should see the Web-PDB UI. Now you can use all PDB commands and features. Additional &#039;&#039;&#039;Current file&#039;&#039;&#039;, &#039;&#039;&#039;Globals&#039;&#039;&#039; and &#039;&#039;&#039;Locals&#039;&#039;&#039; information boxes help you better track your program runtime state.&lt;br /&gt;
&lt;br /&gt;
== More Information ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/romanvm/kodi.web-pdb Web-PDB for Kodi on GitHub].&lt;br /&gt;
* [https://docs.python.org/2/library/pdb.html PDB debugger documentation].&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=Add-on_development&amp;diff=141464</id>
		<title>Add-on development</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=Add-on_development&amp;diff=141464"/>
		<updated>2018-10-13T20:29:31Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: Replaced the link to obsolete WinPDB article (WinPDB is unsupported and seriously outdated)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{mininav|[[Development]]}}&lt;br /&gt;
[[File:Wiki logo.png|150px|link=|left]]&lt;br /&gt;
&amp;lt;section begin=&amp;quot;intro&amp;quot; /&amp;gt;This area contains information, tutorials, and links for creating add-ons (and plug-ins) for Kodi.&amp;lt;section end=&amp;quot;intro&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{-}}&lt;br /&gt;
----&lt;br /&gt;
{{huge|&#039;&#039;&#039;{{color|black|General}}&#039;&#039;&#039;}}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Nuvola apps kthememgr.png|link=About Add-ons}}&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Applications-development.png|link=Add-on structure|title=Add-on Structure}}&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Tool-box-icon.png|link=Development Tools}}&lt;br /&gt;
|}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Administration.png|link=Add-on settings}}&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=60.jpg|link=Special protocol}}&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Translate icon.jpg|link=Translation System}}&lt;br /&gt;
|}&lt;br /&gt;
----&lt;br /&gt;
{{huge|&#039;&#039;&#039;{{color|black|Add-on Types}}&#039;&#039;&#039;}}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Nuvola apps kthememgr.png|link=Plugin sources}}&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Applications-development.png|link=Script sources|title=Scripts}}&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Administration.png|link=Script Subtitles}}&lt;br /&gt;
|}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| width=&amp;quot;25%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Gnome-system-run.png|link=Service addons}}&lt;br /&gt;
| width=&amp;quot;25%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Misc-Misc-Box-icon.png|link=HOW-TO:Create a repository for add-ons|title=Repository add-ons}}&lt;br /&gt;
| width=&amp;quot;25%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Web-icon.png|link=HOW-TO:Write media scrapers|title=Scraper add-ons}}&lt;br /&gt;
| width=&amp;quot;25%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Weather_addon.png|link=Weather_addons}}&lt;br /&gt;
|}&lt;br /&gt;
----&lt;br /&gt;
{{huge|&#039;&#039;&#039;{{color|black|Tutorials}}&#039;&#039;&#039;}}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Translation - Noun project 987.png|link=HOW-TO:HelloWorld_addon|title=Hello World Tutorial}}&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Addons-icon.png|link=Audio/video add-on tutorial|title=General Add-on Tutorial}}&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=script-icon.png|link=HOW-TO:Script_addon|title=Script Tutorial}}&lt;br /&gt;
|}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Video.png|link=3rd Party Tutorials}}&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=music-icon.png|link=HOW-TO:Audio_addon|title=Audio Tutorial}}&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=video-icon.png|link=HOW-TO:Video_addon|title=Video Tutorial}}&lt;br /&gt;
|}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Visualisation-icon.jpg|link=HOW-TO:Visualisation_addon|title=Visualisation Tutorial}}&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Screensaver-icon.png|link=HOW-TO:Screensaver_addon|title=Screensaver Tutorial}}&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=context-menu-icon.png|link=Context_Item_Add-ons|title=Context Item Tutorial}}&lt;br /&gt;
|}&lt;br /&gt;
----&lt;br /&gt;
{{huge|&#039;&#039;&#039;{{color|black|Advanced}}&#039;&#039;&#039;}}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| width=&amp;quot;50%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Book icon 1.png|link=Python Libraries|title=Kodi Python Libraries}}&lt;br /&gt;
| width=&amp;quot;50%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=501159.png‎‎|link=JSON-RPC API}}&lt;br /&gt;
|}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Eclipse_ide_icon_by_necromod-d5lt9zc.png‎|link=HOW-TO:Debug_Python_Scripts_with_Eclipse|title=Debugging with Eclipse}}&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Web-pdb-icon.png‎|link=HOW-TO:Debug_Python_Scripts_with_Web-PDB|title=Debugging with Web-PDB}}&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Unicode icon.jpg|link=Add-on unicode paths}}&lt;br /&gt;
|}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| width=&amp;quot;25%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Apps-Brackets-B-icon.png‎|link=List of built-in functions}}&lt;br /&gt;
| width=&amp;quot;25%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=shopping-list-generator-icon.png‎|link=InfoLabels|title=List of info labels}}&lt;br /&gt;
| width=&amp;quot;25%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Windowsicon.png‎‎|link=Window IDs|title=List of window IDs}}&lt;br /&gt;
| width=&amp;quot;25%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Boolean_operation_icon.jpg‎|link=List of boolean conditions}}&lt;br /&gt;
|}&lt;br /&gt;
----&lt;br /&gt;
{{huge|&#039;&#039;&#039;{{color|black|Publishing}}&#039;&#039;&#039;}}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Upload-128.png|link=Submitting Add-ons}}&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Thumbs up font awesome.png‎|link=Add-on Rules}}&lt;br /&gt;
|}&lt;br /&gt;
----&lt;br /&gt;
{{huge|&#039;&#039;&#039;{{color|black|Repositories}}&#039;&#039;&#039;}}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Thumbnail-symbol-transparent.png|link=Official_add-on_repository|title=Official Add-on Repository}}&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Zappy.png|link=Add-on Website}}&lt;br /&gt;
| width=&amp;quot;33%&amp;quot; align=&amp;quot;center&amp;quot; | {{Main page icon|image=Box_icon.png‎|link=Unofficial add-on repositories|title=Third-party Add-on Repositories}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category:Add-on development|*]]&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=File:Web-pdb-icon.png&amp;diff=141463</id>
		<title>File:Web-pdb-icon.png</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=File:Web-pdb-icon.png&amp;diff=141463"/>
		<updated>2018-10-13T20:26:01Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Web-PDB debugger icon&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=135032</id>
		<title>General information about migration to Python 3</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=135032"/>
		<updated>2018-02-12T12:56:23Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: /* Absolute Import */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Python 3 was released 9 years ago and EOL for Python 2.7 is scheduled for 2020. Currently more and more Python project are switching to Python 3 or 2/3 compatible code. The issue of migrating Kodi’s built-in Python interpreter to Python 3.x was brought up on the Kodi forum several times. Now, thanks to a successful GSOC 2017 project, we have a working Python 3 interpreter for Kodi. That is why on Kodi DevCon 2017 Team Kodi decided that we will switch to Python 3 in the future Kodi release (v.19 preliminarily).&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 3.x versions are not backward-compatible with Python 2.x, so we decided to urge addon developers to start porting their addons to Python 3 by making the addons compatible with both Python 2 and 3 and submitting them to the official repo. This way, when Kodi with Python 3 is released, we won’t have a situation when we have no working addons.&lt;br /&gt;
&lt;br /&gt;
== The Process ==&lt;br /&gt;
&lt;br /&gt;
* Starting from Kodi 18 (Leia), only addons that are compatible with both Python 2 and 3 will be accepted to the official addon repository.&lt;br /&gt;
* We will provide Kodi builds with Python 3 so that addon developers can tests if their addons are really compatible with Python 3.&lt;br /&gt;
* A thread will be created on the Kodi forum so that addon devs can get help with their migration process.&lt;br /&gt;
&lt;br /&gt;
== Python 3 And 2 Differences ==&lt;br /&gt;
&lt;br /&gt;
Below is a brief overview of the main differences between Python 3 and 2.&lt;br /&gt;
&lt;br /&gt;
=== Unicode strings by default ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 built-in &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds the sequence of bytes so it can be used to store both binary data and textual data in ASCII or any of 8-bit fixed-length encodings (there were plenty). Python 2 also has &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; type that can store text in various writing systems. A minimal unit of a &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; object is a Unicode codepoint (a Unicode character). Both &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects can be mixed and matched together, for example, concatenated using &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; operator.&lt;br /&gt;
&lt;br /&gt;
In Python 3 &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds Unicode characters, and for binary data a new &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; type was added. This type was also added to Python 2.7 to simplify porting to Python 3 but in Python 2.7 bytes is simply an alias for &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; types are incompatible, and an attempt to use both together will result in &amp;lt;code&amp;gt;TypeError&amp;lt;/code&amp;gt; exception. A &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; object can be converted to &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; using .decode() method, and a &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; is converted to &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; using .encode() method.&lt;br /&gt;
&lt;br /&gt;
=== Absolute Import ===&lt;br /&gt;
Python 3 uses so called “absolute import” and you can no longer import neighbor modules from inside a package using only a module name. You need to either to use either a fully qualified name or a “dotted” notation.&lt;br /&gt;
&lt;br /&gt;
Let’s assume that you have a &amp;lt;code&amp;gt;foo&amp;lt;/code&amp;gt; package that contains &amp;lt;code&amp;gt;bar&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;spam&amp;lt;/code&amp;gt; modules:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
foo/&lt;br /&gt;
  __init__.py&lt;br /&gt;
  bar.py&lt;br /&gt;
  spam.py    &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
And you need to import &amp;lt;code&amp;gt;bar&amp;lt;/code&amp;gt; module from &amp;lt;code&amp;gt;spam&amp;lt;/code&amp;gt;. In Python 2 you can do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But in Python 3 you need to use either&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import foo.bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from . import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating Point Division ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 applying division operator to int numbers produces int result. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 / 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Python 3 division operator always gives you a float result.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4/3&lt;br /&gt;
1.3333333333333333&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get an int result you need to use integer division operator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 // 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Print Function ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 print statement has been replaced with print() function. This is not very relevant to Kodi because using print in Python addons is discouraged and xbmc.log() function should be used to write messages to the Kodi log.&lt;br /&gt;
&lt;br /&gt;
=== Default Iterators ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 most function and methods that produce sequences return iterators instead of lists. For example, range() function and .items(), .keys(), .values() of dict type produce iterators instead of lists, and their Python 2 analogues — xrange() function and .iter* methods of dict type — have been removed.&lt;br /&gt;
&lt;br /&gt;
=== No long Integers ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 long integer type has been removed and int type can now hold a number of arbitrary length.&lt;br /&gt;
&lt;br /&gt;
Those are only some of the differences between Python 2 and 3. For a more complete list see [https://docs.python.org/3.6/whatsnew/3.0.html official Python documentation].&lt;br /&gt;
&lt;br /&gt;
== Some Useful Information ==&lt;br /&gt;
&lt;br /&gt;
As it was said above, Python 3 includes a number of incompatible changes, so to avoid situation when after upgrading Kodi for Python 3 support most Python addons will be broken developers should start to port their addons to be compatible with both Python 2 and 3. This is not a trivial task but fortunately there are a number of tools and recommendations to simplify this process. Here I’ll give you some advice and information about tools that will simplify creating portable code that runs on both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
=== Know Your Strings! ===&lt;br /&gt;
&lt;br /&gt;
This is the most problematic part of porting Python 2 code to Python 3 so I put it first. One of the most notable differences between Python 2 and 3 is clear separation between “textual” and “binary” strings, that is, between textual data and their binary representation. This difference is often difficult to understand, especially for novice developers (not only in Python), and the fact that in Python 2 you can mix together str (binary data) and unicode (textual data) adds to that difficulty.&lt;br /&gt;
&lt;br /&gt;
There are many explanations in the Internet, but here are the most basic things about strings that you need to know:&lt;br /&gt;
&lt;br /&gt;
“Textual” or Unicode strings (unicode in Python 2 and str in Python 3) hold text as a sequence of characters. A minimal unit in such strings is a Unicode character — an abstract entity that represent an alphabet symbol, a punctuation sign or other symbol included in the Unicode character table. Of course, such symbols have concrete internal binary representation (a computer is a binary machine after all), but this representation is not relevant to us. All you need to know is that “textual” strings contain text units without being tied to concrete binary representation.&lt;br /&gt;
&lt;br /&gt;
Unlike Unicode strings, binary strings (str in Python 2 and bytes in both Python 2 and 3) hold binary data, and a minimal unit of such strings is a byte or 8 bits. Historically, in Python 2 such strings are used for textual data encoded in ASCII or other 1-byte fixed-length encoding (e.g. Windows 1251 for Cyrillic alphabets). However, this approach has its limitation, that is why unicode type was introduced in Python 2, and in Python 3 it was renamed to str and made a default container for textual data.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 2 allows to mix and match Unicode and binary strings in the same context and this creates big problems when porting Python 2 code to Python 3. So in order to successfully port your code to Python 3 you need to carefully consider how textual data are processed in your addon. The following recommendations will help you avoid problems when writing Python 2/3 compatible code.&lt;br /&gt;
&lt;br /&gt;
=== Avoid using binary strings for text ===&lt;br /&gt;
&lt;br /&gt;
Store all your text as Unicode strings. This means that all binary strings received from external sources (textual files, websites, various APIs) need to be decoded using appropriate encoding (UTF-8 in most cases). If you need to use strings literals (although using hardcoded strings for user-facing text in Kodi is strongly discouraged), they need to be defined as unicode strings as well. You can use either&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
at the beginning of your modules to enable unicode strings by default as in Python 3 or u-strings, e.g. &amp;lt;code&amp;gt;u&#039;foo&#039;&amp;lt;/code&amp;gt; (Python 3 understands them too) — it doesn&#039;t really matter as long as you are doing it consistently.&lt;br /&gt;
&lt;br /&gt;
=== Know the libraries you are using ===&lt;br /&gt;
Working with Python Standard Library and third-party libraries (including Kodi Python API) you should know that types their functions and methods expect and what types they return. For example, in popular requests library Response.text property returns a Unicode string and Response.content returns a binary string.&lt;br /&gt;
&lt;br /&gt;
If a function/method/property returns a binary string, you need to decode it to a Unicode string using .decode() method. Don’t use unicode class constructor because unicode type does not exist in Python 3.&lt;br /&gt;
&lt;br /&gt;
If you are reading textual files from disk, it is better to use io.open() instead of built-in open(). io.open() can decode file contents to Unicode using specified encoding and works identically both in Python 2 and 3. Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import io&lt;br /&gt;
&lt;br /&gt;
with io.open(&#039;foo.txt&#039;, &#039;r&#039;, encoding=&#039;utf-8&#039;) as fo:&lt;br /&gt;
   text = fo.read()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Potential pitfalls ===&lt;br /&gt;
&lt;br /&gt;
When writing Python 2/3-compatible code or converting existing Python 2 codebase to compatible code you should pay attention to the following Python language constructions where TypeError exceptions may happen because of incompatible string types if you don’t get your strings in order:&lt;br /&gt;
&lt;br /&gt;
* String concatenations with + operator (&amp;lt;code&amp;gt;&#039;foo&#039; + &#039;bar&#039;&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String formatting — both “old style” (&amp;lt;code&amp;gt;&#039;foo %s&#039; % &#039;bar&#039;&amp;lt;/code&amp;gt;) and “new style” (&amp;lt;code&amp;gt;&#039;foo {}&#039;.format(&#039;bar&#039;)&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String joining (&amp;lt;code&amp;gt;&#039;, &#039;.join([&#039;foo&#039;, &#039;bar&#039;])&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
In all those cases always make sure that you work with Unicode strings only.&lt;br /&gt;
Another source of subtle bugs is functions and methods that accept and return binary strings (str type) in Python 2  but Unicode strings in Python 3 (again, str type but with different properties). You can use the following utility functions to “normalize” strings that are provided to such functions/methods and received from them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
__all__ = [&#039;PY2&#039;, &#039;py2_encode&#039;, &#039;py2_decode&#039;]&lt;br /&gt;
&lt;br /&gt;
PY2 = sys.version_info[0] == 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_encode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Encode Python 2 ``unicode`` to ``str``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.   &lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, unicode):&lt;br /&gt;
       s = s.encode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_decode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Decode Python 2 ``str`` to ``unicode``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, str):&lt;br /&gt;
       s = s.decode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Those utility functions are included in Kodi Six library that is described in the following section.&lt;br /&gt;
&lt;br /&gt;
== Helper Libraries and Tools ==&lt;br /&gt;
&lt;br /&gt;
=== 2to3 ===&lt;br /&gt;
&lt;br /&gt;
[https://docs.python.org/2/library/2to3.html 2to3] script is created by Python developers to help converting existing Python 2 code to Python 3. On Windows it is included in Python distribution (Tools subfolder) but on other OSes you man need to install it separately. For example, on Ubuntu it is included in python-examples package. Note that this script is created for conversion from Python 2 to 3, not for writing portable code, so you need to treat its output with care.&lt;br /&gt;
&lt;br /&gt;
=== Modernize ===&lt;br /&gt;
&lt;br /&gt;
https://python-modernize.readthedocs.io/en/latest/ Modernize] script works on top of 2to3 and is supposed to help you to convert your existing Python 2 code to Python 2/3-compatible. However, in my experiments it did not work reliably even in simple cases so I cannot recommend it for usage.&lt;br /&gt;
&lt;br /&gt;
=== Six ===&lt;br /&gt;
&lt;br /&gt;
[https://pythonhosted.org/six/ Six] was the first library developed to simplify Python 2 to 3 migration. It provides a set of wrappers that hide differences between Python 2 and 3 behind its API. It is less intrusive than the following alternative because it does not monkey-patch built-in names, but in order to use Six library effectively you need to learn its API. Six can be used both for writing new Python 2/3-compatible addons and converting existing ones, but it requires good knowledge of Python 2/3 differences to pick necessary Six features that address specific differences.&lt;br /&gt;
&lt;br /&gt;
Six library is included in the Kodi addon repository as &#039;&#039;&#039;script.module.six&#039;&#039;&#039; addon.&lt;br /&gt;
&lt;br /&gt;
=== Future ===&lt;br /&gt;
&lt;br /&gt;
[http://python-future.org/ Future] library, like Six, was created to simplify porting existing Python 2 code to 3. But it uses a different approach than Six. Future monkey-patches built-in Python objects to make Python 2 behave like Python 3. The advantage of such approach is that code written using Future is close to idiomatic Python 3 and requires little re-work if you decide to drop Python 2 support in the future. However, such approach may cause problems in some rare edge-cases.&lt;br /&gt;
&lt;br /&gt;
Future library also includes &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; command-line utility for converting existing Python 2 code to 2/3-compatible and in my experiments this utility showed good results.&lt;br /&gt;
Future library (without additional utilities) is included in the Kodi addon repository as script.module.future addon.&lt;br /&gt;
&lt;br /&gt;
=== Kodi Six ===&lt;br /&gt;
&lt;br /&gt;
[https://github.com/romanvm/kodi.six Kodi Six] library (available as &#039;&#039;&#039;script.module.kodi-six&#039;&#039;&#039; addon) is created to normalize string handling in Kodi Python API based on different Python versions by applying wrappers around Kodi API functions and classes. In Kodi API based on Python 2 Kodi Six wrappers have the following effects:&lt;br /&gt;
&lt;br /&gt;
* All functions and methods that expect string arguments can accept both UTF-8 encoded &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; objects and &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects.&lt;br /&gt;
* All functions and methods that return string data return &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
In Kodi API based on Python 3 the wrappers have no effect because Python 3-based API works only with &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; (Unicode) objects. This eliminates the need for ad hoc encoding and decoding string when working with Kodi API. To use the wrappers you need to import Kodi API &amp;lt;code&amp;gt;xbmc*&amp;lt;/code&amp;gt; modules from Kodi Six instead of importing them directly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from kodi_six import xbmc, xbmcaddon, xbmcgui, xbmcplugin, xbmcvfs&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== PyCharm ===&lt;br /&gt;
&lt;br /&gt;
PyCharm, except for being a really good Python IDE, also provides code compatibility inspection that helps you write Python 2/3-portable code. Open &#039;&#039;&#039;Settings&#039;&#039;&#039; (Alt+F7) &amp;gt; &#039;&#039;&#039;Editor&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Inspections&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Python&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Code compatibility inspections&#039;&#039;&#039; and check Python version that you want to support.&lt;br /&gt;
&lt;br /&gt;
PyCharm Community Edition is free and provides all features you need for creating Python addons for Kodi.&lt;br /&gt;
&lt;br /&gt;
== Writing Portable Code ==&lt;br /&gt;
&lt;br /&gt;
Here I’ll give you some tips about how to write portable code:&lt;br /&gt;
&lt;br /&gt;
* Learn the differences between Python 2 and 3. You need to know at least the most important differences between the two major Python versions.&lt;br /&gt;
&lt;br /&gt;
* Use version control system — git or mercurial — to track changes in your code. If you are porting existing code, do it in a separate branch.&lt;br /&gt;
&lt;br /&gt;
* No matter if you are going to write a brand new addon or to port existing addon to Python 3, carefully choose your tools. It is totally possible to write portable code without any helper tools and libraries, but you need to know what you are doing. However, in most cases I’d recommend you to use Future library and its utilities. Carefully read Future documentation.&lt;br /&gt;
&lt;br /&gt;
* Put the following line at the beginning of all your modules:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will enable respective Python 3 features in your code. You don’t need to import print_function (another Python 3 feature) because in Kodi addons you should to use xbmc.log() to write messages to the Kodi log file.&lt;br /&gt;
&lt;br /&gt;
=== Writing New Addons ===&lt;br /&gt;
&lt;br /&gt;
Check the [http://python-future.org/quickstart.html#if-you-are-writing-code-from-scratch Quick Start Guide] section of Future library documentation. You can also use Six library, but, as it was said previously, you need to learn its API to pick the necessary features to address specific Python version differences, while Future allows to write your code in (almost) idiomatic Python 3.&lt;br /&gt;
&lt;br /&gt;
A brief procedure for writing new Python 2/3-compatible addons with Future library:&lt;br /&gt;
&lt;br /&gt;
# Create a new virtual environment with Python 3 interpreter and activate it.&lt;br /&gt;
# Install Future library: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Point your IDE (Integrated Development Environment) to that environment. For example, in PyCharm: &#039;&#039;&#039;File&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Setting&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project Interpreter&#039;&#039;&#039;.&lt;br /&gt;
# Put the following line at the beginning of your Python code:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
from future import standard_library&lt;br /&gt;
from future.builtins import *&lt;br /&gt;
standard_library.install_aliases()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Write your addon using Python 3 syntax and standard library names. However, you may still need to use wrappers from Future library for some specific cases (e.g. iterators over &amp;lt;code&amp;gt;dict&amp;lt;/code&amp;gt; elements). Read Future docs for more info.&lt;br /&gt;
&lt;br /&gt;
=== Porting Existing Addons ===&lt;br /&gt;
&lt;br /&gt;
A brief procedure for porting existing code to Python 3-compatible with Future library:&lt;br /&gt;
&lt;br /&gt;
# Install Future library into your working Python 2 virtual environment: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; utility to convert all your scripts and modules to portable code.&lt;br /&gt;
&lt;br /&gt;
Test your new or converted addon in Kodi with Python 2 interpreter and fix all found issues. After that test the addon in Kodi with Python 3 interpreter and again fix all found issues.&lt;br /&gt;
You can use [https://github.com/romanvm/kodi.web-pdb Web-PDB] debugger for troubleshooting issues in your code. It is compatible with both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* Python 2 and 3 differences: https://docs.python.org/3.6/whatsnew/3.0.html&lt;br /&gt;
* Future library documentation: http://python-future.org/&lt;br /&gt;
* Six library documentation: https://pythonhosted.org/six/&lt;br /&gt;
* Kodi test builds with Python 3 for Windows: http://mirrors.xbmc.org/test-builds/windows/win32/&lt;br /&gt;
* Kodi test builds with Python 3 for Linux Ubuntu: https://launchpad.net/~wsnipex/+archive/ubuntu/kodi-python3/+packages&lt;br /&gt;
* “Python 3 migration” section on the Kodi official forum: https://forum.kodi.tv/forumdisplay.php?fid=281&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=133858</id>
		<title>General information about migration to Python 3</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=133858"/>
		<updated>2018-02-04T13:57:34Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: /* Absolute Import */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Python 3 was released 9 years ago and EOL for Python 2.7 is scheduled for 2020. Currently more and more Python project are switching to Python 3 or 2/3 compatible code. The issue of migrating Kodi’s built-in Python interpreter to Python 3.x was brought up on the Kodi forum several times. Now, thanks to a successful GSOC 2017 project, we have a working Python 3 interpreter for Kodi. That is why on Kodi DevCon 2017 Team Kodi decided that we will switch to Python 3 in the future Kodi release (v.19 preliminarily).&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 3.x versions are not backward-compatible with Python 2.x, so we decided to urge addon developers to start porting their addons to Python 3 by making the addons compatible with both Python 2 and 3 and submitting them to the official repo. This way, when Kodi with Python 3 is released, we won’t have a situation when we have no working addons.&lt;br /&gt;
&lt;br /&gt;
== The Process ==&lt;br /&gt;
&lt;br /&gt;
* Starting from Kodi 18 (Leia), only addons that are compatible with both Python 2 and 3 will be accepted to the official addon repository.&lt;br /&gt;
* We will provide Kodi builds with Python 3 so that addon developers can tests if their addons are really compatible with Python 3.&lt;br /&gt;
* A thread will be created on the Kodi forum so that addon devs can get help with their migration process.&lt;br /&gt;
&lt;br /&gt;
== Python 3 And 2 Differences ==&lt;br /&gt;
&lt;br /&gt;
Below is a brief overview of the main differences between Python 3 and 2.&lt;br /&gt;
&lt;br /&gt;
=== Unicode strings by default ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 built-in &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds the sequence of bytes so it can be used to store both binary data and textual data in ASCII or any of 8-bit fixed-length encodings (there were plenty). Python 2 also has &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; type that can store text in various writing systems. A minimal unit of a &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; object is a Unicode codepoint (a Unicode character). Both &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects can be mixed and matched together, for example, concatenated using &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; operator.&lt;br /&gt;
&lt;br /&gt;
In Python 3 &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds Unicode characters, and for binary data a new &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; type was added. This type was also added to Python 2.7 to simplify porting to Python 3 but in Python 2.7 bytes is simply an alias for &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; types are incompatible, and an attempt to use both together will result in &amp;lt;code&amp;gt;TypeError&amp;lt;/code&amp;gt; exception. A &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; object can be converted to &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; using .decode() method, and a &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; is converted to &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; using .encode() method.&lt;br /&gt;
&lt;br /&gt;
=== Absolute Import ===&lt;br /&gt;
Python 3 uses so called “absolute import” and you can no longer import modules from inside a package using only a module name. You need to either to use either a fully qualified name or a “dotted” notation.&lt;br /&gt;
&lt;br /&gt;
Let’s assume that you have a &amp;lt;code&amp;gt;foo&amp;lt;/code&amp;gt; package that contains &amp;lt;code&amp;gt;bar&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;spam&amp;lt;/code&amp;gt; modules:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
foo/&lt;br /&gt;
  __init__.py&lt;br /&gt;
  bar.py&lt;br /&gt;
  spam.py    &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
And you need to import &amp;lt;code&amp;gt;bar&amp;lt;/code&amp;gt; module from &amp;lt;code&amp;gt;spam&amp;lt;/code&amp;gt;. In Python 2 you can do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But in Python 3 you need to use either&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import foo.bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from . import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating Point Division ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 applying division operator to int numbers produces int result. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 / 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Python 3 division operator always gives you a float result.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4/3&lt;br /&gt;
1.3333333333333333&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get an int result you need to use integer division operator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 // 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Print Function ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 print statement has been replaced with print() function. This is not very relevant to Kodi because using print in Python addons is discouraged and xbmc.log() function should be used to write messages to the Kodi log.&lt;br /&gt;
&lt;br /&gt;
=== Default Iterators ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 most function and methods that produce sequences return iterators instead of lists. For example, range() function and .items(), .keys(), .values() of dict type produce iterators instead of lists, and their Python 2 analogues — xrange() function and .iter* methods of dict type — have been removed.&lt;br /&gt;
&lt;br /&gt;
=== No long Integers ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 long integer type has been removed and int type can now hold a number of arbitrary length.&lt;br /&gt;
&lt;br /&gt;
Those are only some of the differences between Python 2 and 3. For a more complete list see [https://docs.python.org/3.6/whatsnew/3.0.html official Python documentation].&lt;br /&gt;
&lt;br /&gt;
== Some Useful Information ==&lt;br /&gt;
&lt;br /&gt;
As it was said above, Python 3 includes a number of incompatible changes, so to avoid situation when after upgrading Kodi for Python 3 support most Python addons will be broken developers should start to port their addons to be compatible with both Python 2 and 3. This is not a trivial task but fortunately there are a number of tools and recommendations to simplify this process. Here I’ll give you some advice and information about tools that will simplify creating portable code that runs on both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
=== Know Your Strings! ===&lt;br /&gt;
&lt;br /&gt;
This is the most problematic part of porting Python 2 code to Python 3 so I put it first. One of the most notable differences between Python 2 and 3 is clear separation between “textual” and “binary” strings, that is, between textual data and their binary representation. This difference is often difficult to understand, especially for novice developers (not only in Python), and the fact that in Python 2 you can mix together str (binary data) and unicode (textual data) adds to that difficulty.&lt;br /&gt;
&lt;br /&gt;
There are many explanations in the Internet, but here are the most basic things about strings that you need to know:&lt;br /&gt;
&lt;br /&gt;
“Textual” or Unicode strings (unicode in Python 2 and str in Python 3) hold text as a sequence of characters. A minimal unit in such strings is a Unicode character — an abstract entity that represent an alphabet symbol, a punctuation sign or other symbol included in the Unicode character table. Of course, such symbols have concrete internal binary representation (a computer is a binary machine after all), but this representation is not relevant to us. All you need to know is that “textual” strings contain text units without being tied to concrete binary representation.&lt;br /&gt;
&lt;br /&gt;
Unlike Unicode strings, binary strings (str in Python 2 and bytes in both Python 2 and 3) hold binary data, and a minimal unit of such strings is a byte or 8 bits. Historically, in Python 2 such strings are used for textual data encoded in ASCII or other 1-byte fixed-length encoding (e.g. Windows 1251 for Cyrillic alphabets). However, this approach has its limitation, that is why unicode type was introduced in Python 2, and in Python 3 it was renamed to str and made a default container for textual data.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 2 allows to mix and match Unicode and binary strings in the same context and this creates big problems when porting Python 2 code to Python 3. So in order to successfully port your code to Python 3 you need to carefully consider how textual data are processed in your addon. The following recommendations will help you avoid problems when writing Python 2/3 compatible code.&lt;br /&gt;
&lt;br /&gt;
=== Avoid using binary strings for text ===&lt;br /&gt;
&lt;br /&gt;
Store all your text as Unicode strings. This means that all binary strings received from external sources (textual files, websites, various APIs) need to be decoded using appropriate encoding (UTF-8 in most cases). If you need to use strings literals (although using hardcoded strings for user-facing text in Kodi is strongly discouraged), they need to be defined as unicode strings as well. You can use either&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
at the beginning of your modules to enable unicode strings by default as in Python 3 or u-strings, e.g. &amp;lt;code&amp;gt;u&#039;foo&#039;&amp;lt;/code&amp;gt; (Python 3 understands them too) — it doesn&#039;t really matter as long as you are doing it consistently.&lt;br /&gt;
&lt;br /&gt;
=== Know the libraries you are using ===&lt;br /&gt;
Working with Python Standard Library and third-party libraries (including Kodi Python API) you should know that types their functions and methods expect and what types they return. For example, in popular requests library Response.text property returns a Unicode string and Response.content returns a binary string.&lt;br /&gt;
&lt;br /&gt;
If a function/method/property returns a binary string, you need to decode it to a Unicode string using .decode() method. Don’t use unicode class constructor because unicode type does not exist in Python 3.&lt;br /&gt;
&lt;br /&gt;
If you are reading textual files from disk, it is better to use io.open() instead of built-in open(). io.open() can decode file contents to Unicode using specified encoding and works identically both in Python 2 and 3. Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import io&lt;br /&gt;
&lt;br /&gt;
with io.open(&#039;foo.txt&#039;, &#039;r&#039;, encoding=&#039;utf-8&#039;) as fo:&lt;br /&gt;
   text = fo.read()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Potential pitfalls ===&lt;br /&gt;
&lt;br /&gt;
When writing Python 2/3-compatible code or converting existing Python 2 codebase to compatible code you should pay attention to the following Python language constructions where TypeError exceptions may happen because of incompatible string types if you don’t get your strings in order:&lt;br /&gt;
&lt;br /&gt;
* String concatenations with + operator (&amp;lt;code&amp;gt;&#039;foo&#039; + &#039;bar&#039;&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String formatting — both “old style” (&amp;lt;code&amp;gt;&#039;foo %s&#039; % &#039;bar&#039;&amp;lt;/code&amp;gt;) and “new style” (&amp;lt;code&amp;gt;&#039;foo {}&#039;.format(&#039;bar&#039;)&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String joining (&amp;lt;code&amp;gt;&#039;, &#039;.join([&#039;foo&#039;, &#039;bar&#039;])&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
In all those cases always make sure that you work with Unicode strings only.&lt;br /&gt;
Another source of subtle bugs is functions and methods that accept and return binary strings (str type) in Python 2  but Unicode strings in Python 3 (again, str type but with different properties). You can use the following utility functions to “normalize” strings that are provided to such functions/methods and received from them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
__all__ = [&#039;PY2&#039;, &#039;py2_encode&#039;, &#039;py2_decode&#039;]&lt;br /&gt;
&lt;br /&gt;
PY2 = sys.version_info[0] == 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_encode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Encode Python 2 ``unicode`` to ``str``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.   &lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, unicode):&lt;br /&gt;
       s = s.encode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_decode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Decode Python 2 ``str`` to ``unicode``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, str):&lt;br /&gt;
       s = s.decode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Those utility functions are included in Kodi Six library that is described in the following section.&lt;br /&gt;
&lt;br /&gt;
== Helper Libraries and Tools ==&lt;br /&gt;
&lt;br /&gt;
=== 2to3 ===&lt;br /&gt;
&lt;br /&gt;
[https://docs.python.org/2/library/2to3.html 2to3] script is created by Python developers to help converting existing Python 2 code to Python 3. On Windows it is included in Python distribution (Tools subfolder) but on other OSes you man need to install it separately. For example, on Ubuntu it is included in python-examples package. Note that this script is created for conversion from Python 2 to 3, not for writing portable code, so you need to treat its output with care.&lt;br /&gt;
&lt;br /&gt;
=== Modernize ===&lt;br /&gt;
&lt;br /&gt;
https://python-modernize.readthedocs.io/en/latest/ Modernize] script works on top of 2to3 and is supposed to help you to convert your existing Python 2 code to Python 2/3-compatible. However, in my experiments it did not work reliably even in simple cases so I cannot recommend it for usage.&lt;br /&gt;
&lt;br /&gt;
=== Six ===&lt;br /&gt;
&lt;br /&gt;
[https://pythonhosted.org/six/ Six] was the first library developed to simplify Python 2 to 3 migration. It provides a set of wrappers that hide differences between Python 2 and 3 behind its API. It is less intrusive than the following alternative because it does not monkey-patch built-in names, but in order to use Six library effectively you need to learn its API. Six can be used both for writing new Python 2/3-compatible addons and converting existing ones, but it requires good knowledge of Python 2/3 differences to pick necessary Six features that address specific differences.&lt;br /&gt;
&lt;br /&gt;
Six library is included in the Kodi addon repository as &#039;&#039;&#039;script.module.six&#039;&#039;&#039; addon.&lt;br /&gt;
&lt;br /&gt;
=== Future ===&lt;br /&gt;
&lt;br /&gt;
[http://python-future.org/ Future] library, like Six, was created to simplify porting existing Python 2 code to 3. But it uses a different approach than Six. Future monkey-patches built-in Python objects to make Python 2 behave like Python 3. The advantage of such approach is that code written using Future is close to idiomatic Python 3 and requires little re-work if you decide to drop Python 2 support in the future. However, such approach may cause problems in some rare edge-cases.&lt;br /&gt;
&lt;br /&gt;
Future library also includes &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; command-line utility for converting existing Python 2 code to 2/3-compatible and in my experiments this utility showed good results.&lt;br /&gt;
Future library (without additional utilities) is included in the Kodi addon repository as script.module.future addon.&lt;br /&gt;
&lt;br /&gt;
=== Kodi Six ===&lt;br /&gt;
&lt;br /&gt;
[https://github.com/romanvm/kodi.six Kodi Six] library (available as &#039;&#039;&#039;script.module.kodi-six&#039;&#039;&#039; addon) is created to normalize string handling in Kodi Python API based on different Python versions by applying wrappers around Kodi API functions and classes. In Kodi API based on Python 2 Kodi Six wrappers have the following effects:&lt;br /&gt;
&lt;br /&gt;
* All functions and methods that expect string arguments can accept both UTF-8 encoded &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; objects and &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects.&lt;br /&gt;
* All functions and methods that return string data return &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
In Kodi API based on Python 3 the wrappers have no effect because Python 3-based API works only with &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; (Unicode) objects. This eliminates the need for ad hoc encoding and decoding string when working with Kodi API. To use the wrappers you need to import Kodi API &amp;lt;code&amp;gt;xbmc*&amp;lt;/code&amp;gt; modules from Kodi Six instead of importing them directly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from kodi_six import xbmc, xbmcaddon, xbmcgui, xbmcplugin, xbmcvfs&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== PyCharm ===&lt;br /&gt;
&lt;br /&gt;
PyCharm, except for being a really good Python IDE, also provides code compatibility inspection that helps you write Python 2/3-portable code. Open &#039;&#039;&#039;Settings&#039;&#039;&#039; (Alt+F7) &amp;gt; &#039;&#039;&#039;Editor&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Inspections&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Python&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Code compatibility inspections&#039;&#039;&#039; and check Python version that you want to support.&lt;br /&gt;
&lt;br /&gt;
PyCharm Community Edition is free and provides all features you need for creating Python addons for Kodi.&lt;br /&gt;
&lt;br /&gt;
== Writing Portable Code ==&lt;br /&gt;
&lt;br /&gt;
Here I’ll give you some tips about how to write portable code:&lt;br /&gt;
&lt;br /&gt;
* Learn the differences between Python 2 and 3. You need to know at least the most important differences between the two major Python versions.&lt;br /&gt;
&lt;br /&gt;
* Use version control system — git or mercurial — to track changes in your code. If you are porting existing code, do it in a separate branch.&lt;br /&gt;
&lt;br /&gt;
* No matter if you are going to write a brand new addon or to port existing addon to Python 3, carefully choose your tools. It is totally possible to write portable code without any helper tools and libraries, but you need to know what you are doing. However, in most cases I’d recommend you to use Future library and its utilities. Carefully read Future documentation.&lt;br /&gt;
&lt;br /&gt;
* Put the following line at the beginning of all your modules:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will enable respective Python 3 features in your code. You don’t need to import print_function (another Python 3 feature) because in Kodi addons you should to use xbmc.log() to write messages to the Kodi log file.&lt;br /&gt;
&lt;br /&gt;
=== Writing New Addons ===&lt;br /&gt;
&lt;br /&gt;
Check the [http://python-future.org/quickstart.html#if-you-are-writing-code-from-scratch Quick Start Guide] section of Future library documentation. You can also use Six library, but, as it was said previously, you need to learn its API to pick the necessary features to address specific Python version differences, while Future allows to write your code in (almost) idiomatic Python 3.&lt;br /&gt;
&lt;br /&gt;
A brief procedure for writing new Python 2/3-compatible addons with Future library:&lt;br /&gt;
&lt;br /&gt;
# Create a new virtual environment with Python 3 interpreter and activate it.&lt;br /&gt;
# Install Future library: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Point your IDE (Integrated Development Environment) to that environment. For example, in PyCharm: &#039;&#039;&#039;File&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Setting&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project Interpreter&#039;&#039;&#039;.&lt;br /&gt;
# Put the following line at the beginning of your Python code:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
from future import standard_library&lt;br /&gt;
from future.builtins import *&lt;br /&gt;
standard_library.install_aliases()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Write your addon using Python 3 syntax and standard library names. However, you may still need to use wrappers from Future library for some specific cases (e.g. iterators over &amp;lt;code&amp;gt;dict&amp;lt;/code&amp;gt; elements). Read Future docs for more info.&lt;br /&gt;
&lt;br /&gt;
=== Porting Existing Addons ===&lt;br /&gt;
&lt;br /&gt;
A brief procedure for porting existing code to Python 3-compatible with Future library:&lt;br /&gt;
&lt;br /&gt;
# Install Future library into your working Python 2 virtual environment: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; utility to convert all your scripts and modules to portable code.&lt;br /&gt;
&lt;br /&gt;
Test your new or converted addon in Kodi with Python 2 interpreter and fix all found issues. After that test the addon in Kodi with Python 3 interpreter and again fix all found issues.&lt;br /&gt;
You can use [https://github.com/romanvm/kodi.web-pdb Web-PDB] debugger for troubleshooting issues in your code. It is compatible with both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* Python 2 and 3 differences: https://docs.python.org/3.6/whatsnew/3.0.html&lt;br /&gt;
* Future library documentation: http://python-future.org/&lt;br /&gt;
* Six library documentation: https://pythonhosted.org/six/&lt;br /&gt;
* Kodi test builds with Python 3 for Windows: http://mirrors.xbmc.org/test-builds/windows/win32/&lt;br /&gt;
* Kodi test builds with Python 3 for Linux Ubuntu: https://launchpad.net/~wsnipex/+archive/ubuntu/kodi-python3/+packages&lt;br /&gt;
* “Python 3 migration” section on the Kodi official forum: https://forum.kodi.tv/forumdisplay.php?fid=281&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132482</id>
		<title>General information about migration to Python 3</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132482"/>
		<updated>2018-01-19T11:55:41Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: /* Potential pitfalls */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Python 3 was released 9 years ago and EOL for Python 2.7 is scheduled for 2020. Currently more and more Python project are switching to Python 3 or 2/3 compatible code. The issue of migrating Kodi’s built-in Python interpreter to Python 3.x was brought up on the Kodi forum several times. Now, thanks to a successful GSOC 2017 project, we have a working Python 3 interpreter for Kodi. That is why on Kodi DevCon 2017 Team Kodi decided that we will switch to Python 3 in the future Kodi release (v.19 preliminarily).&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 3.x versions are not backward-compatible with Python 2.x, so we decided to urge addon developers to start porting their addons to Python 3 by making the addons compatible with both Python 2 and 3 and submitting them to the official repo. This way, when Kodi with Python 3 is released, we won’t have a situation when we have no working addons.&lt;br /&gt;
&lt;br /&gt;
== The Process ==&lt;br /&gt;
&lt;br /&gt;
* Starting from Kodi 18 (Leia), only addons that are compatible with both Python 2 and 3 will be accepted to the official addon repository.&lt;br /&gt;
* We will provide Kodi builds with Python 3 so that addon developers can tests if their addons are really compatible with Python 3.&lt;br /&gt;
* A thread will be created on the Kodi forum so that addon devs can get help with their migration process.&lt;br /&gt;
&lt;br /&gt;
== Python 3 And 2 Differences ==&lt;br /&gt;
&lt;br /&gt;
Below is a brief overview of the main differences between Python 3 and 2.&lt;br /&gt;
&lt;br /&gt;
=== Unicode strings by default ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 built-in &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds the sequence of bytes so it can be used to store both binary data and textual data in ASCII or any of 8-bit fixed-length encodings (there were plenty). Python 2 also has &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; type that can store text in various writing systems. A minimal unit of a &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; object is a Unicode codepoint (a Unicode character). Both &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects can be mixed and matched together, for example, concatenated using &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; operator.&lt;br /&gt;
&lt;br /&gt;
In Python 3 &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds Unicode characters, and for binary data a new &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; type was added. This type was also added to Python 2.7 to simplify porting to Python 3 but in Python 2.7 bytes is simply an alias for &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; types are incompatible, and an attempt to use both together will result in &amp;lt;code&amp;gt;TypeError&amp;lt;/code&amp;gt; exception. A &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; object can be converted to &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; using .decode() method, and a &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; is converted to &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; using .encode() method.&lt;br /&gt;
&lt;br /&gt;
=== Absolute Import ===&lt;br /&gt;
Python 3 uses so called “absolute import” and you can no longer import modules from inside a package using only a module name. You need to either to use either a fully qualified name or a “dotted” notation.&lt;br /&gt;
&lt;br /&gt;
Let’s assume that you have a foo package that contains bar and spam modules, and you need to import bar module from spam. In Python 2 you can do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But in Python 3 you need to use either&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import foo.bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from . import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating Point Division ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 applying division operator to int numbers produces int result. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 / 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Python 3 division operator always gives you a float result.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4/3&lt;br /&gt;
1.3333333333333333&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get an int result you need to use integer division operator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 // 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Print Function ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 print statement has been replaced with print() function. This is not very relevant to Kodi because using print in Python addons is discouraged and xbmc.log() function should be used to write messages to the Kodi log.&lt;br /&gt;
&lt;br /&gt;
=== Default Iterators ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 most function and methods that produce sequences return iterators instead of lists. For example, range() function and .items(), .keys(), .values() of dict type produce iterators instead of lists, and their Python 2 analogues — xrange() function and .iter* methods of dict type — have been removed.&lt;br /&gt;
&lt;br /&gt;
=== No long Integers ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 long integer type has been removed and int type can now hold a number of arbitrary length.&lt;br /&gt;
&lt;br /&gt;
Those are only some of the differences between Python 2 and 3. For a more complete list see [https://docs.python.org/3.6/whatsnew/3.0.html official Python documentation].&lt;br /&gt;
&lt;br /&gt;
== Some Useful Information ==&lt;br /&gt;
&lt;br /&gt;
As it was said above, Python 3 includes a number of incompatible changes, so to avoid situation when after upgrading Kodi for Python 3 support most Python addons will be broken developers should start to port their addons to be compatible with both Python 2 and 3. This is not a trivial task but fortunately there are a number of tools and recommendations to simplify this process. Here I’ll give you some advice and information about tools that will simplify creating portable code that runs on both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
=== Know Your Strings! ===&lt;br /&gt;
&lt;br /&gt;
This is the most problematic part of porting Python 2 code to Python 3 so I put it first. One of the most notable differences between Python 2 and 3 is clear separation between “textual” and “binary” strings, that is, between textual data and their binary representation. This difference is often difficult to understand, especially for novice developers (not only in Python), and the fact that in Python 2 you can mix together str (binary data) and unicode (textual data) adds to that difficulty.&lt;br /&gt;
&lt;br /&gt;
There are many explanations in the Internet, but here are the most basic things about strings that you need to know:&lt;br /&gt;
&lt;br /&gt;
“Textual” or Unicode strings (unicode in Python 2 and str in Python 3) hold text as a sequence of characters. A minimal unit in such strings is a Unicode character — an abstract entity that represent an alphabet symbol, a punctuation sign or other symbol included in the Unicode character table. Of course, such symbols have concrete internal binary representation (a computer is a binary machine after all), but this representation is not relevant to us. All you need to know is that “textual” strings contain text units without being tied to concrete binary representation.&lt;br /&gt;
&lt;br /&gt;
Unlike Unicode strings, binary strings (str in Python 2 and bytes in both Python 2 and 3) hold binary data, and a minimal unit of such strings is a byte or 8 bits. Historically, in Python 2 such strings are used for textual data encoded in ASCII or other 1-byte fixed-length encoding (e.g. Windows 1251 for Cyrillic alphabets). However, this approach has its limitation, that is why unicode type was introduced in Python 2, and in Python 3 it was renamed to str and made a default container for textual data.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 2 allows to mix and match Unicode and binary strings in the same context and this creates big problems when porting Python 2 code to Python 3. So in order to successfully port your code to Python 3 you need to carefully consider how textual data are processed in your addon. The following recommendations will help you avoid problems when writing Python 2/3 compatible code.&lt;br /&gt;
&lt;br /&gt;
=== Avoid using binary strings for text ===&lt;br /&gt;
&lt;br /&gt;
Store all your text as Unicode strings. This means that all binary strings received from external sources (textual files, websites, various APIs) need to be decoded using appropriate encoding (UTF-8 in most cases). If you need to use strings literals (although using hardcoded strings for user-facing text in Kodi is strongly discouraged), they need to be defined as unicode strings as well. You can use either&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
at the beginning of your modules to enable unicode strings by default as in Python 3 or u-strings, e.g. &amp;lt;code&amp;gt;u&#039;foo&#039;&amp;lt;/code&amp;gt; (Python 3 understands them too) — it doesn&#039;t really matter as long as you are doing it consistently.&lt;br /&gt;
&lt;br /&gt;
=== Know the libraries you are using ===&lt;br /&gt;
Working with Python Standard Library and third-party libraries (including Kodi Python API) you should know that types their functions and methods expect and what types they return. For example, in popular requests library Response.text property returns a Unicode string and Response.content returns a binary string.&lt;br /&gt;
&lt;br /&gt;
If a function/method/property returns a binary string, you need to decode it to a Unicode string using .decode() method. Don’t use unicode class constructor because unicode type does not exist in Python 3.&lt;br /&gt;
&lt;br /&gt;
If you are reading textual files from disk, it is better to use io.open() instead of built-in open(). io.open() can decode file contents to Unicode using specified encoding and works identically both in Python 2 and 3. Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import io&lt;br /&gt;
&lt;br /&gt;
with io.open(&#039;foo.txt&#039;, &#039;r&#039;, encoding=&#039;utf-8&#039;) as fo:&lt;br /&gt;
   text = fo.read()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Potential pitfalls ===&lt;br /&gt;
&lt;br /&gt;
When writing Python 2/3-compatible code or converting existing Python 2 codebase to compatible code you should pay attention to the following Python language constructions where TypeError exceptions may happen because of incompatible string types if you don’t get your strings in order:&lt;br /&gt;
&lt;br /&gt;
* String concatenations with + operator (&amp;lt;code&amp;gt;&#039;foo&#039; + &#039;bar&#039;&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String formatting — both “old style” (&amp;lt;code&amp;gt;&#039;foo %s&#039; % &#039;bar&#039;&amp;lt;/code&amp;gt;) and “new style” (&amp;lt;code&amp;gt;&#039;foo {}&#039;.format(&#039;bar&#039;)&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String joining (&amp;lt;code&amp;gt;&#039;, &#039;.join([&#039;foo&#039;, &#039;bar&#039;])&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
In all those cases always make sure that you work with Unicode strings only.&lt;br /&gt;
Another source of subtle bugs is functions and methods that accept and return binary strings (str type) in Python 2  but Unicode strings in Python 3 (again, str type but with different properties). You can use the following utility functions to “normalize” strings that are provided to such functions/methods and received from them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
__all__ = [&#039;PY2&#039;, &#039;py2_encode&#039;, &#039;py2_decode&#039;]&lt;br /&gt;
&lt;br /&gt;
PY2 = sys.version_info[0] == 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_encode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Encode Python 2 ``unicode`` to ``str``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.   &lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, unicode):&lt;br /&gt;
       s = s.encode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_decode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Decode Python 2 ``str`` to ``unicode``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, str):&lt;br /&gt;
       s = s.decode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Those utility functions are included in Kodi Six library that is described in the following section.&lt;br /&gt;
&lt;br /&gt;
== Helper Libraries and Tools ==&lt;br /&gt;
&lt;br /&gt;
=== 2to3 ===&lt;br /&gt;
&lt;br /&gt;
[https://docs.python.org/2/library/2to3.html 2to3] script is created by Python developers to help converting existing Python 2 code to Python 3. On Windows it is included in Python distribution (Tools subfolder) but on other OSes you man need to install it separately. For example, on Ubuntu it is included in python-examples package. Note that this script is created for conversion from Python 2 to 3, not for writing portable code, so you need to treat its output with care.&lt;br /&gt;
&lt;br /&gt;
=== Modernize ===&lt;br /&gt;
&lt;br /&gt;
https://python-modernize.readthedocs.io/en/latest/ Modernize] script works on top of 2to3 and is supposed to help you to convert your existing Python 2 code to Python 2/3-compatible. However, in my experiments it did not work reliably even in simple cases so I cannot recommend it for usage.&lt;br /&gt;
&lt;br /&gt;
=== Six ===&lt;br /&gt;
&lt;br /&gt;
[https://pythonhosted.org/six/ Six] was the first library developed to simplify Python 2 to 3 migration. It provides a set of wrappers that hide differences between Python 2 and 3 behind its API. It is less intrusive than the following alternative because it does not monkey-patch built-in names, but in order to use Six library effectively you need to learn its API. Six can be used both for writing new Python 2/3-compatible addons and converting existing ones, but it requires good knowledge of Python 2/3 differences to pick necessary Six features that address specific differences.&lt;br /&gt;
&lt;br /&gt;
Six library is included in the Kodi addon repository as &#039;&#039;&#039;script.module.six&#039;&#039;&#039; addon.&lt;br /&gt;
&lt;br /&gt;
=== Future ===&lt;br /&gt;
&lt;br /&gt;
[http://python-future.org/ Future] library, like Six, was created to simplify porting existing Python 2 code to 3. But it uses a different approach than Six. Future monkey-patches built-in Python objects to make Python 2 behave like Python 3. The advantage of such approach is that code written using Future is close to idiomatic Python 3 and requires little re-work if you decide to drop Python 2 support in the future. However, such approach may cause problems in some rare edge-cases.&lt;br /&gt;
&lt;br /&gt;
Future library also includes &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; command-line utility for converting existing Python 2 code to 2/3-compatible and in my experiments this utility showed good results.&lt;br /&gt;
Future library (without additional utilities) is included in the Kodi addon repository as script.module.future addon.&lt;br /&gt;
&lt;br /&gt;
=== Kodi Six ===&lt;br /&gt;
&lt;br /&gt;
[https://github.com/romanvm/kodi.six Kodi Six] library (available as &#039;&#039;&#039;script.module.kodi-six&#039;&#039;&#039; addon) is created to normalize string handling in Kodi Python API based on different Python versions by applying wrappers around Kodi API functions and classes. In Kodi API based on Python 2 Kodi Six wrappers have the following effects:&lt;br /&gt;
&lt;br /&gt;
* All functions and methods that expect string arguments can accept both UTF-8 encoded &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; objects and &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects.&lt;br /&gt;
* All functions and methods that return string data return &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
In Kodi API based on Python 3 the wrappers have no effect because Python 3-based API works only with &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; (Unicode) objects. This eliminates the need for ad hoc encoding and decoding string when working with Kodi API. To use the wrappers you need to import Kodi API &amp;lt;code&amp;gt;xbmc*&amp;lt;/code&amp;gt; modules from Kodi Six instead of importing them directly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from kodi_six import xbmc, xbmcaddon, xbmcgui, xbmcplugin, xbmcvfs&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== PyCharm ===&lt;br /&gt;
&lt;br /&gt;
PyCharm, except for being a really good Python IDE, also provides code compatibility inspection that helps you write Python 2/3-portable code. Open &#039;&#039;&#039;Settings&#039;&#039;&#039; (Alt+F7) &amp;gt; &#039;&#039;&#039;Editor&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Inspections&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Python&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Code compatibility inspections&#039;&#039;&#039; and check Python version that you want to support.&lt;br /&gt;
&lt;br /&gt;
PyCharm Community Edition is free and provides all features you need for creating Python addons for Kodi.&lt;br /&gt;
&lt;br /&gt;
== Writing Portable Code ==&lt;br /&gt;
&lt;br /&gt;
Here I’ll give you some tips about how to write portable code:&lt;br /&gt;
&lt;br /&gt;
* Learn the differences between Python 2 and 3. You need to know at least the most important differences between the two major Python versions.&lt;br /&gt;
&lt;br /&gt;
* Use version control system — git or mercurial — to track changes in your code. If you are porting existing code, do it in a separate branch.&lt;br /&gt;
&lt;br /&gt;
* No matter if you are going to write a brand new addon or to port existing addon to Python 3, carefully choose your tools. It is totally possible to write portable code without any helper tools and libraries, but you need to know what you are doing. However, in most cases I’d recommend you to use Future library and its utilities. Carefully read Future documentation.&lt;br /&gt;
&lt;br /&gt;
* Put the following line at the beginning of all your modules:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will enable respective Python 3 features in your code. You don’t need to import print_function (another Python 3 feature) because in Kodi addons you should to use xbmc.log() to write messages to the Kodi log file.&lt;br /&gt;
&lt;br /&gt;
=== Writing New Addons ===&lt;br /&gt;
&lt;br /&gt;
Check the [http://python-future.org/quickstart.html#if-you-are-writing-code-from-scratch Quick Start Guide] section of Future library documentation. You can also use Six library, but, as it was said previously, you need to learn its API to pick the necessary features to address specific Python version differences, while Future allows to write your code in (almost) idiomatic Python 3.&lt;br /&gt;
&lt;br /&gt;
A brief procedure for writing new Python 2/3-compatible addons with Future library:&lt;br /&gt;
&lt;br /&gt;
# Create a new virtual environment with Python 3 interpreter and activate it.&lt;br /&gt;
# Install Future library: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Point your IDE (Integrated Development Environment) to that environment. For example, in PyCharm: &#039;&#039;&#039;File&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Setting&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project Interpreter&#039;&#039;&#039;.&lt;br /&gt;
# Put the following line at the beginning of your Python code:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
from future import standard_library&lt;br /&gt;
from future.builtins import *&lt;br /&gt;
standard_library.install_aliases()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Write your addon using Python 3 syntax and standard library names. However, you may still need to use wrappers from Future library for some specific cases (e.g. iterators over &amp;lt;code&amp;gt;dict&amp;lt;/code&amp;gt; elements). Read Future docs for more info.&lt;br /&gt;
&lt;br /&gt;
=== Porting Existing Addons ===&lt;br /&gt;
&lt;br /&gt;
A brief procedure for porting existing code to Python 3-compatible with Future library:&lt;br /&gt;
&lt;br /&gt;
# Install Future library into your working Python 2 virtual environment: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; utility to convert all your scripts and modules to portable code.&lt;br /&gt;
&lt;br /&gt;
Test your new or converted addon in Kodi with Python 2 interpreter and fix all found issues. After that test the addon in Kodi with Python 3 interpreter and again fix all found issues.&lt;br /&gt;
You can use [https://github.com/romanvm/kodi.web-pdb Web-PDB] debugger for troubleshooting issues in your code. It is compatible with both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* Python 2 and 3 differences: https://docs.python.org/3.6/whatsnew/3.0.html&lt;br /&gt;
* Future library documentation: http://python-future.org/&lt;br /&gt;
* Six library documentation: https://pythonhosted.org/six/&lt;br /&gt;
* Kodi test builds with Python 3 for Windows: http://mirrors.xbmc.org/test-builds/windows/win32/&lt;br /&gt;
* Kodi test builds with Python 3 for Linux Ubuntu: https://launchpad.net/~wsnipex/+archive/ubuntu/kodi-python3/+packages&lt;br /&gt;
* “Python 3 migration” section on the Kodi official forum: https://forum.kodi.tv/forumdisplay.php?fid=281&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132481</id>
		<title>General information about migration to Python 3</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132481"/>
		<updated>2018-01-19T11:54:32Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: /* Helper Libraries and Tools */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Python 3 was released 9 years ago and EOL for Python 2.7 is scheduled for 2020. Currently more and more Python project are switching to Python 3 or 2/3 compatible code. The issue of migrating Kodi’s built-in Python interpreter to Python 3.x was brought up on the Kodi forum several times. Now, thanks to a successful GSOC 2017 project, we have a working Python 3 interpreter for Kodi. That is why on Kodi DevCon 2017 Team Kodi decided that we will switch to Python 3 in the future Kodi release (v.19 preliminarily).&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 3.x versions are not backward-compatible with Python 2.x, so we decided to urge addon developers to start porting their addons to Python 3 by making the addons compatible with both Python 2 and 3 and submitting them to the official repo. This way, when Kodi with Python 3 is released, we won’t have a situation when we have no working addons.&lt;br /&gt;
&lt;br /&gt;
== The Process ==&lt;br /&gt;
&lt;br /&gt;
* Starting from Kodi 18 (Leia), only addons that are compatible with both Python 2 and 3 will be accepted to the official addon repository.&lt;br /&gt;
* We will provide Kodi builds with Python 3 so that addon developers can tests if their addons are really compatible with Python 3.&lt;br /&gt;
* A thread will be created on the Kodi forum so that addon devs can get help with their migration process.&lt;br /&gt;
&lt;br /&gt;
== Python 3 And 2 Differences ==&lt;br /&gt;
&lt;br /&gt;
Below is a brief overview of the main differences between Python 3 and 2.&lt;br /&gt;
&lt;br /&gt;
=== Unicode strings by default ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 built-in &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds the sequence of bytes so it can be used to store both binary data and textual data in ASCII or any of 8-bit fixed-length encodings (there were plenty). Python 2 also has &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; type that can store text in various writing systems. A minimal unit of a &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; object is a Unicode codepoint (a Unicode character). Both &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects can be mixed and matched together, for example, concatenated using &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; operator.&lt;br /&gt;
&lt;br /&gt;
In Python 3 &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds Unicode characters, and for binary data a new &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; type was added. This type was also added to Python 2.7 to simplify porting to Python 3 but in Python 2.7 bytes is simply an alias for &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; types are incompatible, and an attempt to use both together will result in &amp;lt;code&amp;gt;TypeError&amp;lt;/code&amp;gt; exception. A &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; object can be converted to &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; using .decode() method, and a &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; is converted to &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; using .encode() method.&lt;br /&gt;
&lt;br /&gt;
=== Absolute Import ===&lt;br /&gt;
Python 3 uses so called “absolute import” and you can no longer import modules from inside a package using only a module name. You need to either to use either a fully qualified name or a “dotted” notation.&lt;br /&gt;
&lt;br /&gt;
Let’s assume that you have a foo package that contains bar and spam modules, and you need to import bar module from spam. In Python 2 you can do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But in Python 3 you need to use either&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import foo.bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from . import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating Point Division ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 applying division operator to int numbers produces int result. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 / 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Python 3 division operator always gives you a float result.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4/3&lt;br /&gt;
1.3333333333333333&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get an int result you need to use integer division operator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 // 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Print Function ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 print statement has been replaced with print() function. This is not very relevant to Kodi because using print in Python addons is discouraged and xbmc.log() function should be used to write messages to the Kodi log.&lt;br /&gt;
&lt;br /&gt;
=== Default Iterators ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 most function and methods that produce sequences return iterators instead of lists. For example, range() function and .items(), .keys(), .values() of dict type produce iterators instead of lists, and their Python 2 analogues — xrange() function and .iter* methods of dict type — have been removed.&lt;br /&gt;
&lt;br /&gt;
=== No long Integers ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 long integer type has been removed and int type can now hold a number of arbitrary length.&lt;br /&gt;
&lt;br /&gt;
Those are only some of the differences between Python 2 and 3. For a more complete list see [https://docs.python.org/3.6/whatsnew/3.0.html official Python documentation].&lt;br /&gt;
&lt;br /&gt;
== Some Useful Information ==&lt;br /&gt;
&lt;br /&gt;
As it was said above, Python 3 includes a number of incompatible changes, so to avoid situation when after upgrading Kodi for Python 3 support most Python addons will be broken developers should start to port their addons to be compatible with both Python 2 and 3. This is not a trivial task but fortunately there are a number of tools and recommendations to simplify this process. Here I’ll give you some advice and information about tools that will simplify creating portable code that runs on both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
=== Know Your Strings! ===&lt;br /&gt;
&lt;br /&gt;
This is the most problematic part of porting Python 2 code to Python 3 so I put it first. One of the most notable differences between Python 2 and 3 is clear separation between “textual” and “binary” strings, that is, between textual data and their binary representation. This difference is often difficult to understand, especially for novice developers (not only in Python), and the fact that in Python 2 you can mix together str (binary data) and unicode (textual data) adds to that difficulty.&lt;br /&gt;
&lt;br /&gt;
There are many explanations in the Internet, but here are the most basic things about strings that you need to know:&lt;br /&gt;
&lt;br /&gt;
“Textual” or Unicode strings (unicode in Python 2 and str in Python 3) hold text as a sequence of characters. A minimal unit in such strings is a Unicode character — an abstract entity that represent an alphabet symbol, a punctuation sign or other symbol included in the Unicode character table. Of course, such symbols have concrete internal binary representation (a computer is a binary machine after all), but this representation is not relevant to us. All you need to know is that “textual” strings contain text units without being tied to concrete binary representation.&lt;br /&gt;
&lt;br /&gt;
Unlike Unicode strings, binary strings (str in Python 2 and bytes in both Python 2 and 3) hold binary data, and a minimal unit of such strings is a byte or 8 bits. Historically, in Python 2 such strings are used for textual data encoded in ASCII or other 1-byte fixed-length encoding (e.g. Windows 1251 for Cyrillic alphabets). However, this approach has its limitation, that is why unicode type was introduced in Python 2, and in Python 3 it was renamed to str and made a default container for textual data.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 2 allows to mix and match Unicode and binary strings in the same context and this creates big problems when porting Python 2 code to Python 3. So in order to successfully port your code to Python 3 you need to carefully consider how textual data are processed in your addon. The following recommendations will help you avoid problems when writing Python 2/3 compatible code.&lt;br /&gt;
&lt;br /&gt;
=== Avoid using binary strings for text ===&lt;br /&gt;
&lt;br /&gt;
Store all your text as Unicode strings. This means that all binary strings received from external sources (textual files, websites, various APIs) need to be decoded using appropriate encoding (UTF-8 in most cases). If you need to use strings literals (although using hardcoded strings for user-facing text in Kodi is strongly discouraged), they need to be defined as unicode strings as well. You can use either&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
at the beginning of your modules to enable unicode strings by default as in Python 3 or u-strings, e.g. &amp;lt;code&amp;gt;u&#039;foo&#039;&amp;lt;/code&amp;gt; (Python 3 understands them too) — it doesn&#039;t really matter as long as you are doing it consistently.&lt;br /&gt;
&lt;br /&gt;
=== Know the libraries you are using ===&lt;br /&gt;
Working with Python Standard Library and third-party libraries (including Kodi Python API) you should know that types their functions and methods expect and what types they return. For example, in popular requests library Response.text property returns a Unicode string and Response.content returns a binary string.&lt;br /&gt;
&lt;br /&gt;
If a function/method/property returns a binary string, you need to decode it to a Unicode string using .decode() method. Don’t use unicode class constructor because unicode type does not exist in Python 3.&lt;br /&gt;
&lt;br /&gt;
If you are reading textual files from disk, it is better to use io.open() instead of built-in open(). io.open() can decode file contents to Unicode using specified encoding and works identically both in Python 2 and 3. Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import io&lt;br /&gt;
&lt;br /&gt;
with io.open(&#039;foo.txt&#039;, &#039;r&#039;, encoding=&#039;utf-8&#039;) as fo:&lt;br /&gt;
   text = fo.read()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Potential pitfalls ===&lt;br /&gt;
&lt;br /&gt;
When writing Python 2/3-compatible code or converting existing Python 2 codebase to compatible code you should pay attention to the following Python language constructions where TypeError exceptions may happen because of incompatible string types if you don’t get your strings in order:&lt;br /&gt;
&lt;br /&gt;
* String concatenations with + operator (&amp;lt;code&amp;gt;&#039;foo&#039; + &#039;bar&#039;&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String formatting — both “old style” (&amp;lt;code&amp;gt;&#039;foo %s&#039; % &#039;bar&#039;&amp;lt;/code&amp;gt;) and “new style” (&amp;lt;code&amp;gt;&#039;foo {}&#039;.format(&#039;bar&#039;)&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String joining (&amp;lt;code&amp;gt;&#039;, &#039;.join([&#039;foo&#039;, &#039;bar&#039;])&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
In all those cases always make sure that you work with Unicode strings only.&lt;br /&gt;
Another source of subtle bugs is functions and methods that accept and return binary strings (str type) in Python 2  but Unicode strings in Python 3 (again, str type but with different properties). You can use the following utility functions to “normalize” strings that are provided to such functions/methods and received from them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
__all__ = [&#039;PY2&#039;, &#039;py2_encode&#039;, &#039;py2_decode&#039;]&lt;br /&gt;
&lt;br /&gt;
PY2 = sys.version_info[0] == 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_encode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Encode Python 2 ``unicode`` to ``str``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.   &lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, unicode):&lt;br /&gt;
       s = s.encode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_decode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Decode Python 2 ``str`` to ``unicode``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, str):&lt;br /&gt;
       s = s.decode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Helper Libraries and Tools ==&lt;br /&gt;
&lt;br /&gt;
=== 2to3 ===&lt;br /&gt;
&lt;br /&gt;
[https://docs.python.org/2/library/2to3.html 2to3] script is created by Python developers to help converting existing Python 2 code to Python 3. On Windows it is included in Python distribution (Tools subfolder) but on other OSes you man need to install it separately. For example, on Ubuntu it is included in python-examples package. Note that this script is created for conversion from Python 2 to 3, not for writing portable code, so you need to treat its output with care.&lt;br /&gt;
&lt;br /&gt;
=== Modernize ===&lt;br /&gt;
&lt;br /&gt;
https://python-modernize.readthedocs.io/en/latest/ Modernize] script works on top of 2to3 and is supposed to help you to convert your existing Python 2 code to Python 2/3-compatible. However, in my experiments it did not work reliably even in simple cases so I cannot recommend it for usage.&lt;br /&gt;
&lt;br /&gt;
=== Six ===&lt;br /&gt;
&lt;br /&gt;
[https://pythonhosted.org/six/ Six] was the first library developed to simplify Python 2 to 3 migration. It provides a set of wrappers that hide differences between Python 2 and 3 behind its API. It is less intrusive than the following alternative because it does not monkey-patch built-in names, but in order to use Six library effectively you need to learn its API. Six can be used both for writing new Python 2/3-compatible addons and converting existing ones, but it requires good knowledge of Python 2/3 differences to pick necessary Six features that address specific differences.&lt;br /&gt;
&lt;br /&gt;
Six library is included in the Kodi addon repository as &#039;&#039;&#039;script.module.six&#039;&#039;&#039; addon.&lt;br /&gt;
&lt;br /&gt;
=== Future ===&lt;br /&gt;
&lt;br /&gt;
[http://python-future.org/ Future] library, like Six, was created to simplify porting existing Python 2 code to 3. But it uses a different approach than Six. Future monkey-patches built-in Python objects to make Python 2 behave like Python 3. The advantage of such approach is that code written using Future is close to idiomatic Python 3 and requires little re-work if you decide to drop Python 2 support in the future. However, such approach may cause problems in some rare edge-cases.&lt;br /&gt;
&lt;br /&gt;
Future library also includes &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; command-line utility for converting existing Python 2 code to 2/3-compatible and in my experiments this utility showed good results.&lt;br /&gt;
Future library (without additional utilities) is included in the Kodi addon repository as script.module.future addon.&lt;br /&gt;
&lt;br /&gt;
=== Kodi Six ===&lt;br /&gt;
&lt;br /&gt;
[https://github.com/romanvm/kodi.six Kodi Six] library (available as &#039;&#039;&#039;script.module.kodi-six&#039;&#039;&#039; addon) is created to normalize string handling in Kodi Python API based on different Python versions by applying wrappers around Kodi API functions and classes. In Kodi API based on Python 2 Kodi Six wrappers have the following effects:&lt;br /&gt;
&lt;br /&gt;
* All functions and methods that expect string arguments can accept both UTF-8 encoded &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; objects and &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects.&lt;br /&gt;
* All functions and methods that return string data return &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
In Kodi API based on Python 3 the wrappers have no effect because Python 3-based API works only with &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; (Unicode) objects. This eliminates the need for ad hoc encoding and decoding string when working with Kodi API. To use the wrappers you need to import Kodi API &amp;lt;code&amp;gt;xbmc*&amp;lt;/code&amp;gt; modules from Kodi Six instead of importing them directly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from kodi_six import xbmc, xbmcaddon, xbmcgui, xbmcplugin, xbmcvfs&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== PyCharm ===&lt;br /&gt;
&lt;br /&gt;
PyCharm, except for being a really good Python IDE, also provides code compatibility inspection that helps you write Python 2/3-portable code. Open &#039;&#039;&#039;Settings&#039;&#039;&#039; (Alt+F7) &amp;gt; &#039;&#039;&#039;Editor&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Inspections&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Python&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Code compatibility inspections&#039;&#039;&#039; and check Python version that you want to support.&lt;br /&gt;
&lt;br /&gt;
PyCharm Community Edition is free and provides all features you need for creating Python addons for Kodi.&lt;br /&gt;
&lt;br /&gt;
== Writing Portable Code ==&lt;br /&gt;
&lt;br /&gt;
Here I’ll give you some tips about how to write portable code:&lt;br /&gt;
&lt;br /&gt;
* Learn the differences between Python 2 and 3. You need to know at least the most important differences between the two major Python versions.&lt;br /&gt;
&lt;br /&gt;
* Use version control system — git or mercurial — to track changes in your code. If you are porting existing code, do it in a separate branch.&lt;br /&gt;
&lt;br /&gt;
* No matter if you are going to write a brand new addon or to port existing addon to Python 3, carefully choose your tools. It is totally possible to write portable code without any helper tools and libraries, but you need to know what you are doing. However, in most cases I’d recommend you to use Future library and its utilities. Carefully read Future documentation.&lt;br /&gt;
&lt;br /&gt;
* Put the following line at the beginning of all your modules:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will enable respective Python 3 features in your code. You don’t need to import print_function (another Python 3 feature) because in Kodi addons you should to use xbmc.log() to write messages to the Kodi log file.&lt;br /&gt;
&lt;br /&gt;
=== Writing New Addons ===&lt;br /&gt;
&lt;br /&gt;
Check the [http://python-future.org/quickstart.html#if-you-are-writing-code-from-scratch Quick Start Guide] section of Future library documentation. You can also use Six library, but, as it was said previously, you need to learn its API to pick the necessary features to address specific Python version differences, while Future allows to write your code in (almost) idiomatic Python 3.&lt;br /&gt;
&lt;br /&gt;
A brief procedure for writing new Python 2/3-compatible addons with Future library:&lt;br /&gt;
&lt;br /&gt;
# Create a new virtual environment with Python 3 interpreter and activate it.&lt;br /&gt;
# Install Future library: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Point your IDE (Integrated Development Environment) to that environment. For example, in PyCharm: &#039;&#039;&#039;File&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Setting&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project Interpreter&#039;&#039;&#039;.&lt;br /&gt;
# Put the following line at the beginning of your Python code:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
from future import standard_library&lt;br /&gt;
from future.builtins import *&lt;br /&gt;
standard_library.install_aliases()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Write your addon using Python 3 syntax and standard library names. However, you may still need to use wrappers from Future library for some specific cases (e.g. iterators over &amp;lt;code&amp;gt;dict&amp;lt;/code&amp;gt; elements). Read Future docs for more info.&lt;br /&gt;
&lt;br /&gt;
=== Porting Existing Addons ===&lt;br /&gt;
&lt;br /&gt;
A brief procedure for porting existing code to Python 3-compatible with Future library:&lt;br /&gt;
&lt;br /&gt;
# Install Future library into your working Python 2 virtual environment: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; utility to convert all your scripts and modules to portable code.&lt;br /&gt;
&lt;br /&gt;
Test your new or converted addon in Kodi with Python 2 interpreter and fix all found issues. After that test the addon in Kodi with Python 3 interpreter and again fix all found issues.&lt;br /&gt;
You can use [https://github.com/romanvm/kodi.web-pdb Web-PDB] debugger for troubleshooting issues in your code. It is compatible with both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* Python 2 and 3 differences: https://docs.python.org/3.6/whatsnew/3.0.html&lt;br /&gt;
* Future library documentation: http://python-future.org/&lt;br /&gt;
* Six library documentation: https://pythonhosted.org/six/&lt;br /&gt;
* Kodi test builds with Python 3 for Windows: http://mirrors.xbmc.org/test-builds/windows/win32/&lt;br /&gt;
* Kodi test builds with Python 3 for Linux Ubuntu: https://launchpad.net/~wsnipex/+archive/ubuntu/kodi-python3/+packages&lt;br /&gt;
* “Python 3 migration” section on the Kodi official forum: https://forum.kodi.tv/forumdisplay.php?fid=281&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132480</id>
		<title>General information about migration to Python 3</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132480"/>
		<updated>2018-01-19T09:59:59Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: /* Six */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Python 3 was released 9 years ago and EOL for Python 2.7 is scheduled for 2020. Currently more and more Python project are switching to Python 3 or 2/3 compatible code. The issue of migrating Kodi’s built-in Python interpreter to Python 3.x was brought up on the Kodi forum several times. Now, thanks to a successful GSOC 2017 project, we have a working Python 3 interpreter for Kodi. That is why on Kodi DevCon 2017 Team Kodi decided that we will switch to Python 3 in the future Kodi release (v.19 preliminarily).&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 3.x versions are not backward-compatible with Python 2.x, so we decided to urge addon developers to start porting their addons to Python 3 by making the addons compatible with both Python 2 and 3 and submitting them to the official repo. This way, when Kodi with Python 3 is released, we won’t have a situation when we have no working addons.&lt;br /&gt;
&lt;br /&gt;
== The Process ==&lt;br /&gt;
&lt;br /&gt;
* Starting from Kodi 18 (Leia), only addons that are compatible with both Python 2 and 3 will be accepted to the official addon repository.&lt;br /&gt;
* We will provide Kodi builds with Python 3 so that addon developers can tests if their addons are really compatible with Python 3.&lt;br /&gt;
* A thread will be created on the Kodi forum so that addon devs can get help with their migration process.&lt;br /&gt;
&lt;br /&gt;
== Python 3 And 2 Differences ==&lt;br /&gt;
&lt;br /&gt;
Below is a brief overview of the main differences between Python 3 and 2.&lt;br /&gt;
&lt;br /&gt;
=== Unicode strings by default ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 built-in &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds the sequence of bytes so it can be used to store both binary data and textual data in ASCII or any of 8-bit fixed-length encodings (there were plenty). Python 2 also has &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; type that can store text in various writing systems. A minimal unit of a &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; object is a Unicode codepoint (a Unicode character). Both &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects can be mixed and matched together, for example, concatenated using &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; operator.&lt;br /&gt;
&lt;br /&gt;
In Python 3 &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds Unicode characters, and for binary data a new &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; type was added. This type was also added to Python 2.7 to simplify porting to Python 3 but in Python 2.7 bytes is simply an alias for &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; types are incompatible, and an attempt to use both together will result in &amp;lt;code&amp;gt;TypeError&amp;lt;/code&amp;gt; exception. A &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; object can be converted to &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; using .decode() method, and a &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; is converted to &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; using .encode() method.&lt;br /&gt;
&lt;br /&gt;
=== Absolute Import ===&lt;br /&gt;
Python 3 uses so called “absolute import” and you can no longer import modules from inside a package using only a module name. You need to either to use either a fully qualified name or a “dotted” notation.&lt;br /&gt;
&lt;br /&gt;
Let’s assume that you have a foo package that contains bar and spam modules, and you need to import bar module from spam. In Python 2 you can do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But in Python 3 you need to use either&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import foo.bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from . import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating Point Division ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 applying division operator to int numbers produces int result. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 / 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Python 3 division operator always gives you a float result.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4/3&lt;br /&gt;
1.3333333333333333&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get an int result you need to use integer division operator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 // 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Print Function ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 print statement has been replaced with print() function. This is not very relevant to Kodi because using print in Python addons is discouraged and xbmc.log() function should be used to write messages to the Kodi log.&lt;br /&gt;
&lt;br /&gt;
=== Default Iterators ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 most function and methods that produce sequences return iterators instead of lists. For example, range() function and .items(), .keys(), .values() of dict type produce iterators instead of lists, and their Python 2 analogues — xrange() function and .iter* methods of dict type — have been removed.&lt;br /&gt;
&lt;br /&gt;
=== No long Integers ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 long integer type has been removed and int type can now hold a number of arbitrary length.&lt;br /&gt;
&lt;br /&gt;
Those are only some of the differences between Python 2 and 3. For a more complete list see [https://docs.python.org/3.6/whatsnew/3.0.html official Python documentation].&lt;br /&gt;
&lt;br /&gt;
== Some Useful Information ==&lt;br /&gt;
&lt;br /&gt;
As it was said above, Python 3 includes a number of incompatible changes, so to avoid situation when after upgrading Kodi for Python 3 support most Python addons will be broken developers should start to port their addons to be compatible with both Python 2 and 3. This is not a trivial task but fortunately there are a number of tools and recommendations to simplify this process. Here I’ll give you some advice and information about tools that will simplify creating portable code that runs on both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
=== Know Your Strings! ===&lt;br /&gt;
&lt;br /&gt;
This is the most problematic part of porting Python 2 code to Python 3 so I put it first. One of the most notable differences between Python 2 and 3 is clear separation between “textual” and “binary” strings, that is, between textual data and their binary representation. This difference is often difficult to understand, especially for novice developers (not only in Python), and the fact that in Python 2 you can mix together str (binary data) and unicode (textual data) adds to that difficulty.&lt;br /&gt;
&lt;br /&gt;
There are many explanations in the Internet, but here are the most basic things about strings that you need to know:&lt;br /&gt;
&lt;br /&gt;
“Textual” or Unicode strings (unicode in Python 2 and str in Python 3) hold text as a sequence of characters. A minimal unit in such strings is a Unicode character — an abstract entity that represent an alphabet symbol, a punctuation sign or other symbol included in the Unicode character table. Of course, such symbols have concrete internal binary representation (a computer is a binary machine after all), but this representation is not relevant to us. All you need to know is that “textual” strings contain text units without being tied to concrete binary representation.&lt;br /&gt;
&lt;br /&gt;
Unlike Unicode strings, binary strings (str in Python 2 and bytes in both Python 2 and 3) hold binary data, and a minimal unit of such strings is a byte or 8 bits. Historically, in Python 2 such strings are used for textual data encoded in ASCII or other 1-byte fixed-length encoding (e.g. Windows 1251 for Cyrillic alphabets). However, this approach has its limitation, that is why unicode type was introduced in Python 2, and in Python 3 it was renamed to str and made a default container for textual data.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 2 allows to mix and match Unicode and binary strings in the same context and this creates big problems when porting Python 2 code to Python 3. So in order to successfully port your code to Python 3 you need to carefully consider how textual data are processed in your addon. The following recommendations will help you avoid problems when writing Python 2/3 compatible code.&lt;br /&gt;
&lt;br /&gt;
=== Avoid using binary strings for text ===&lt;br /&gt;
&lt;br /&gt;
Store all your text as Unicode strings. This means that all binary strings received from external sources (textual files, websites, various APIs) need to be decoded using appropriate encoding (UTF-8 in most cases). If you need to use strings literals (although using hardcoded strings for user-facing text in Kodi is strongly discouraged), they need to be defined as unicode strings as well. You can use either&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
at the beginning of your modules to enable unicode strings by default as in Python 3 or u-strings, e.g. &amp;lt;code&amp;gt;u&#039;foo&#039;&amp;lt;/code&amp;gt; (Python 3 understands them too) — it doesn&#039;t really matter as long as you are doing it consistently.&lt;br /&gt;
&lt;br /&gt;
=== Know the libraries you are using ===&lt;br /&gt;
Working with Python Standard Library and third-party libraries (including Kodi Python API) you should know that types their functions and methods expect and what types they return. For example, in popular requests library Response.text property returns a Unicode string and Response.content returns a binary string.&lt;br /&gt;
&lt;br /&gt;
If a function/method/property returns a binary string, you need to decode it to a Unicode string using .decode() method. Don’t use unicode class constructor because unicode type does not exist in Python 3.&lt;br /&gt;
&lt;br /&gt;
If you are reading textual files from disk, it is better to use io.open() instead of built-in open(). io.open() can decode file contents to Unicode using specified encoding and works identically both in Python 2 and 3. Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import io&lt;br /&gt;
&lt;br /&gt;
with io.open(&#039;foo.txt&#039;, &#039;r&#039;, encoding=&#039;utf-8&#039;) as fo:&lt;br /&gt;
   text = fo.read()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Potential pitfalls ===&lt;br /&gt;
&lt;br /&gt;
When writing Python 2/3-compatible code or converting existing Python 2 codebase to compatible code you should pay attention to the following Python language constructions where TypeError exceptions may happen because of incompatible string types if you don’t get your strings in order:&lt;br /&gt;
&lt;br /&gt;
* String concatenations with + operator (&amp;lt;code&amp;gt;&#039;foo&#039; + &#039;bar&#039;&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String formatting — both “old style” (&amp;lt;code&amp;gt;&#039;foo %s&#039; % &#039;bar&#039;&amp;lt;/code&amp;gt;) and “new style” (&amp;lt;code&amp;gt;&#039;foo {}&#039;.format(&#039;bar&#039;)&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String joining (&amp;lt;code&amp;gt;&#039;, &#039;.join([&#039;foo&#039;, &#039;bar&#039;])&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
In all those cases always make sure that you work with Unicode strings only.&lt;br /&gt;
Another source of subtle bugs is functions and methods that accept and return binary strings (str type) in Python 2  but Unicode strings in Python 3 (again, str type but with different properties). You can use the following utility functions to “normalize” strings that are provided to such functions/methods and received from them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
__all__ = [&#039;PY2&#039;, &#039;py2_encode&#039;, &#039;py2_decode&#039;]&lt;br /&gt;
&lt;br /&gt;
PY2 = sys.version_info[0] == 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_encode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Encode Python 2 ``unicode`` to ``str``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.   &lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, unicode):&lt;br /&gt;
       s = s.encode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_decode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Decode Python 2 ``str`` to ``unicode``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, str):&lt;br /&gt;
       s = s.decode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Helper Libraries and Tools ==&lt;br /&gt;
&lt;br /&gt;
=== 2to3 ===&lt;br /&gt;
&lt;br /&gt;
[https://docs.python.org/2/library/2to3.html 2to3] script is created by Python developers to help converting existing Python 2 code to Python 3. On Windows it is included in Python distribution (Tools subfolder) but on other OSes you man need to install it separately. For example, on Ubuntu it is included in python-examples package. Note that this script is created for conversion from Python 2 to 3, not for writing portable code, so you need to treat its output with care.&lt;br /&gt;
&lt;br /&gt;
=== Modernize ===&lt;br /&gt;
&lt;br /&gt;
https://python-modernize.readthedocs.io/en/latest/ Modernize] script works on top of 2to3 and is supposed to help you to convert your existing Python 2 code to Python 2/3-compatible. However, in my experiments it did not work reliably even in simple cases so I cannot recommend it for usage.&lt;br /&gt;
&lt;br /&gt;
=== Six ===&lt;br /&gt;
&lt;br /&gt;
[https://pythonhosted.org/six/ Six] was the first library developed to simplify Python 2 to 3 migration. It provides a set of wrappers that hide differences between Python 2 and 3 behind its API. It is less intrusive than the following alternative because it does not monkey-patch built-in names, but in order to use Six library effectively you need to learn its API. Six can be used both for writing new Python 2/3-compatible addons and converting existing ones, but it requires good knowledge of Python 2/3 differences to pick necessary Six features that address specific differences.&lt;br /&gt;
&lt;br /&gt;
Six library is included in the Kodi addon repository as &#039;&#039;&#039;script.module.six&#039;&#039;&#039; addon.&lt;br /&gt;
&lt;br /&gt;
=== Future ===&lt;br /&gt;
&lt;br /&gt;
[http://python-future.org/ Future] library, like Six, was created to simplify porting existing Python 2 code to 3. But it uses a different approach than Six. Future monkey-patches built-in Python objects to make Python 2 behave like Python 3. The advantage of such approach is that code written using Future is close to idiomatic Python 3 and requires little re-work if you decide to drop Python 2 support in the future. However, such approach may cause problems in some rare edge-cases.&lt;br /&gt;
&lt;br /&gt;
Future library also includes &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; command-line utility for converting existing Python 2 code to 2/3-compatible and in my experiments this utility showed good results.&lt;br /&gt;
Future library (without additional utilities) is included in the Kodi addon repository as script.module.future addon.&lt;br /&gt;
&lt;br /&gt;
=== PyCharm ===&lt;br /&gt;
&lt;br /&gt;
PyCharm, except for being a really good Python IDE, also provides code compatibility inspection that helps you write Python 2/3-portable code. Open &#039;&#039;&#039;Settings&#039;&#039;&#039; (Alt+F7) &amp;gt; &#039;&#039;&#039;Editor&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Inspections&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Python&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Code compatibility inspections&#039;&#039;&#039; and check Python version that you want to support.&lt;br /&gt;
&lt;br /&gt;
PyCharm Community Edition is free and provides all features you need for creating Python addons for Kodi.&lt;br /&gt;
&lt;br /&gt;
== Writing Portable Code ==&lt;br /&gt;
&lt;br /&gt;
Here I’ll give you some tips about how to write portable code:&lt;br /&gt;
&lt;br /&gt;
* Learn the differences between Python 2 and 3. You need to know at least the most important differences between the two major Python versions.&lt;br /&gt;
&lt;br /&gt;
* Use version control system — git or mercurial — to track changes in your code. If you are porting existing code, do it in a separate branch.&lt;br /&gt;
&lt;br /&gt;
* No matter if you are going to write a brand new addon or to port existing addon to Python 3, carefully choose your tools. It is totally possible to write portable code without any helper tools and libraries, but you need to know what you are doing. However, in most cases I’d recommend you to use Future library and its utilities. Carefully read Future documentation.&lt;br /&gt;
&lt;br /&gt;
* Put the following line at the beginning of all your modules:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will enable respective Python 3 features in your code. You don’t need to import print_function (another Python 3 feature) because in Kodi addons you should to use xbmc.log() to write messages to the Kodi log file.&lt;br /&gt;
&lt;br /&gt;
=== Writing New Addons ===&lt;br /&gt;
&lt;br /&gt;
Check the [http://python-future.org/quickstart.html#if-you-are-writing-code-from-scratch Quick Start Guide] section of Future library documentation. You can also use Six library, but, as it was said previously, you need to learn its API to pick the necessary features to address specific Python version differences, while Future allows to write your code in (almost) idiomatic Python 3.&lt;br /&gt;
&lt;br /&gt;
A brief procedure for writing new Python 2/3-compatible addons with Future library:&lt;br /&gt;
&lt;br /&gt;
# Create a new virtual environment with Python 3 interpreter and activate it.&lt;br /&gt;
# Install Future library: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Point your IDE (Integrated Development Environment) to that environment. For example, in PyCharm: &#039;&#039;&#039;File&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Setting&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project Interpreter&#039;&#039;&#039;.&lt;br /&gt;
# Put the following line at the beginning of your Python code:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
from future import standard_library&lt;br /&gt;
from future.builtins import *&lt;br /&gt;
standard_library.install_aliases()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Write your addon using Python 3 syntax and standard library names. However, you may still need to use wrappers from Future library for some specific cases (e.g. iterators over &amp;lt;code&amp;gt;dict&amp;lt;/code&amp;gt; elements). Read Future docs for more info.&lt;br /&gt;
&lt;br /&gt;
=== Porting Existing Addons ===&lt;br /&gt;
&lt;br /&gt;
A brief procedure for porting existing code to Python 3-compatible with Future library:&lt;br /&gt;
&lt;br /&gt;
# Install Future library into your working Python 2 virtual environment: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; utility to convert all your scripts and modules to portable code.&lt;br /&gt;
&lt;br /&gt;
Test your new or converted addon in Kodi with Python 2 interpreter and fix all found issues. After that test the addon in Kodi with Python 3 interpreter and again fix all found issues.&lt;br /&gt;
You can use [https://github.com/romanvm/kodi.web-pdb Web-PDB] debugger for troubleshooting issues in your code. It is compatible with both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* Python 2 and 3 differences: https://docs.python.org/3.6/whatsnew/3.0.html&lt;br /&gt;
* Future library documentation: http://python-future.org/&lt;br /&gt;
* Six library documentation: https://pythonhosted.org/six/&lt;br /&gt;
* Kodi test builds with Python 3 for Windows: http://mirrors.xbmc.org/test-builds/windows/win32/&lt;br /&gt;
* Kodi test builds with Python 3 for Linux Ubuntu: https://launchpad.net/~wsnipex/+archive/ubuntu/kodi-python3/+packages&lt;br /&gt;
* “Python 3 migration” section on the Kodi official forum: https://forum.kodi.tv/forumdisplay.php?fid=281&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132479</id>
		<title>General information about migration to Python 3</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132479"/>
		<updated>2018-01-19T09:58:46Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: /* Writing New Addons */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Python 3 was released 9 years ago and EOL for Python 2.7 is scheduled for 2020. Currently more and more Python project are switching to Python 3 or 2/3 compatible code. The issue of migrating Kodi’s built-in Python interpreter to Python 3.x was brought up on the Kodi forum several times. Now, thanks to a successful GSOC 2017 project, we have a working Python 3 interpreter for Kodi. That is why on Kodi DevCon 2017 Team Kodi decided that we will switch to Python 3 in the future Kodi release (v.19 preliminarily).&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 3.x versions are not backward-compatible with Python 2.x, so we decided to urge addon developers to start porting their addons to Python 3 by making the addons compatible with both Python 2 and 3 and submitting them to the official repo. This way, when Kodi with Python 3 is released, we won’t have a situation when we have no working addons.&lt;br /&gt;
&lt;br /&gt;
== The Process ==&lt;br /&gt;
&lt;br /&gt;
* Starting from Kodi 18 (Leia), only addons that are compatible with both Python 2 and 3 will be accepted to the official addon repository.&lt;br /&gt;
* We will provide Kodi builds with Python 3 so that addon developers can tests if their addons are really compatible with Python 3.&lt;br /&gt;
* A thread will be created on the Kodi forum so that addon devs can get help with their migration process.&lt;br /&gt;
&lt;br /&gt;
== Python 3 And 2 Differences ==&lt;br /&gt;
&lt;br /&gt;
Below is a brief overview of the main differences between Python 3 and 2.&lt;br /&gt;
&lt;br /&gt;
=== Unicode strings by default ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 built-in &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds the sequence of bytes so it can be used to store both binary data and textual data in ASCII or any of 8-bit fixed-length encodings (there were plenty). Python 2 also has &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; type that can store text in various writing systems. A minimal unit of a &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; object is a Unicode codepoint (a Unicode character). Both &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects can be mixed and matched together, for example, concatenated using &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; operator.&lt;br /&gt;
&lt;br /&gt;
In Python 3 &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds Unicode characters, and for binary data a new &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; type was added. This type was also added to Python 2.7 to simplify porting to Python 3 but in Python 2.7 bytes is simply an alias for &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; types are incompatible, and an attempt to use both together will result in &amp;lt;code&amp;gt;TypeError&amp;lt;/code&amp;gt; exception. A &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; object can be converted to &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; using .decode() method, and a &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; is converted to &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; using .encode() method.&lt;br /&gt;
&lt;br /&gt;
=== Absolute Import ===&lt;br /&gt;
Python 3 uses so called “absolute import” and you can no longer import modules from inside a package using only a module name. You need to either to use either a fully qualified name or a “dotted” notation.&lt;br /&gt;
&lt;br /&gt;
Let’s assume that you have a foo package that contains bar and spam modules, and you need to import bar module from spam. In Python 2 you can do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But in Python 3 you need to use either&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import foo.bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from . import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating Point Division ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 applying division operator to int numbers produces int result. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 / 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Python 3 division operator always gives you a float result.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4/3&lt;br /&gt;
1.3333333333333333&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get an int result you need to use integer division operator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 // 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Print Function ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 print statement has been replaced with print() function. This is not very relevant to Kodi because using print in Python addons is discouraged and xbmc.log() function should be used to write messages to the Kodi log.&lt;br /&gt;
&lt;br /&gt;
=== Default Iterators ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 most function and methods that produce sequences return iterators instead of lists. For example, range() function and .items(), .keys(), .values() of dict type produce iterators instead of lists, and their Python 2 analogues — xrange() function and .iter* methods of dict type — have been removed.&lt;br /&gt;
&lt;br /&gt;
=== No long Integers ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 long integer type has been removed and int type can now hold a number of arbitrary length.&lt;br /&gt;
&lt;br /&gt;
Those are only some of the differences between Python 2 and 3. For a more complete list see [https://docs.python.org/3.6/whatsnew/3.0.html official Python documentation].&lt;br /&gt;
&lt;br /&gt;
== Some Useful Information ==&lt;br /&gt;
&lt;br /&gt;
As it was said above, Python 3 includes a number of incompatible changes, so to avoid situation when after upgrading Kodi for Python 3 support most Python addons will be broken developers should start to port their addons to be compatible with both Python 2 and 3. This is not a trivial task but fortunately there are a number of tools and recommendations to simplify this process. Here I’ll give you some advice and information about tools that will simplify creating portable code that runs on both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
=== Know Your Strings! ===&lt;br /&gt;
&lt;br /&gt;
This is the most problematic part of porting Python 2 code to Python 3 so I put it first. One of the most notable differences between Python 2 and 3 is clear separation between “textual” and “binary” strings, that is, between textual data and their binary representation. This difference is often difficult to understand, especially for novice developers (not only in Python), and the fact that in Python 2 you can mix together str (binary data) and unicode (textual data) adds to that difficulty.&lt;br /&gt;
&lt;br /&gt;
There are many explanations in the Internet, but here are the most basic things about strings that you need to know:&lt;br /&gt;
&lt;br /&gt;
“Textual” or Unicode strings (unicode in Python 2 and str in Python 3) hold text as a sequence of characters. A minimal unit in such strings is a Unicode character — an abstract entity that represent an alphabet symbol, a punctuation sign or other symbol included in the Unicode character table. Of course, such symbols have concrete internal binary representation (a computer is a binary machine after all), but this representation is not relevant to us. All you need to know is that “textual” strings contain text units without being tied to concrete binary representation.&lt;br /&gt;
&lt;br /&gt;
Unlike Unicode strings, binary strings (str in Python 2 and bytes in both Python 2 and 3) hold binary data, and a minimal unit of such strings is a byte or 8 bits. Historically, in Python 2 such strings are used for textual data encoded in ASCII or other 1-byte fixed-length encoding (e.g. Windows 1251 for Cyrillic alphabets). However, this approach has its limitation, that is why unicode type was introduced in Python 2, and in Python 3 it was renamed to str and made a default container for textual data.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 2 allows to mix and match Unicode and binary strings in the same context and this creates big problems when porting Python 2 code to Python 3. So in order to successfully port your code to Python 3 you need to carefully consider how textual data are processed in your addon. The following recommendations will help you avoid problems when writing Python 2/3 compatible code.&lt;br /&gt;
&lt;br /&gt;
=== Avoid using binary strings for text ===&lt;br /&gt;
&lt;br /&gt;
Store all your text as Unicode strings. This means that all binary strings received from external sources (textual files, websites, various APIs) need to be decoded using appropriate encoding (UTF-8 in most cases). If you need to use strings literals (although using hardcoded strings for user-facing text in Kodi is strongly discouraged), they need to be defined as unicode strings as well. You can use either&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
at the beginning of your modules to enable unicode strings by default as in Python 3 or u-strings, e.g. &amp;lt;code&amp;gt;u&#039;foo&#039;&amp;lt;/code&amp;gt; (Python 3 understands them too) — it doesn&#039;t really matter as long as you are doing it consistently.&lt;br /&gt;
&lt;br /&gt;
=== Know the libraries you are using ===&lt;br /&gt;
Working with Python Standard Library and third-party libraries (including Kodi Python API) you should know that types their functions and methods expect and what types they return. For example, in popular requests library Response.text property returns a Unicode string and Response.content returns a binary string.&lt;br /&gt;
&lt;br /&gt;
If a function/method/property returns a binary string, you need to decode it to a Unicode string using .decode() method. Don’t use unicode class constructor because unicode type does not exist in Python 3.&lt;br /&gt;
&lt;br /&gt;
If you are reading textual files from disk, it is better to use io.open() instead of built-in open(). io.open() can decode file contents to Unicode using specified encoding and works identically both in Python 2 and 3. Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import io&lt;br /&gt;
&lt;br /&gt;
with io.open(&#039;foo.txt&#039;, &#039;r&#039;, encoding=&#039;utf-8&#039;) as fo:&lt;br /&gt;
   text = fo.read()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Potential pitfalls ===&lt;br /&gt;
&lt;br /&gt;
When writing Python 2/3-compatible code or converting existing Python 2 codebase to compatible code you should pay attention to the following Python language constructions where TypeError exceptions may happen because of incompatible string types if you don’t get your strings in order:&lt;br /&gt;
&lt;br /&gt;
* String concatenations with + operator (&amp;lt;code&amp;gt;&#039;foo&#039; + &#039;bar&#039;&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String formatting — both “old style” (&amp;lt;code&amp;gt;&#039;foo %s&#039; % &#039;bar&#039;&amp;lt;/code&amp;gt;) and “new style” (&amp;lt;code&amp;gt;&#039;foo {}&#039;.format(&#039;bar&#039;)&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String joining (&amp;lt;code&amp;gt;&#039;, &#039;.join([&#039;foo&#039;, &#039;bar&#039;])&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
In all those cases always make sure that you work with Unicode strings only.&lt;br /&gt;
Another source of subtle bugs is functions and methods that accept and return binary strings (str type) in Python 2  but Unicode strings in Python 3 (again, str type but with different properties). You can use the following utility functions to “normalize” strings that are provided to such functions/methods and received from them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
__all__ = [&#039;PY2&#039;, &#039;py2_encode&#039;, &#039;py2_decode&#039;]&lt;br /&gt;
&lt;br /&gt;
PY2 = sys.version_info[0] == 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_encode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Encode Python 2 ``unicode`` to ``str``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.   &lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, unicode):&lt;br /&gt;
       s = s.encode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_decode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Decode Python 2 ``str`` to ``unicode``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, str):&lt;br /&gt;
       s = s.decode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Helper Libraries and Tools ==&lt;br /&gt;
&lt;br /&gt;
=== 2to3 ===&lt;br /&gt;
&lt;br /&gt;
[https://docs.python.org/2/library/2to3.html 2to3] script is created by Python developers to help converting existing Python 2 code to Python 3. On Windows it is included in Python distribution (Tools subfolder) but on other OSes you man need to install it separately. For example, on Ubuntu it is included in python-examples package. Note that this script is created for conversion from Python 2 to 3, not for writing portable code, so you need to treat its output with care.&lt;br /&gt;
&lt;br /&gt;
=== Modernize ===&lt;br /&gt;
&lt;br /&gt;
https://python-modernize.readthedocs.io/en/latest/ Modernize] script works on top of 2to3 and is supposed to help you to convert your existing Python 2 code to Python 2/3-compatible. However, in my experiments it did not work reliably even in simple cases so I cannot recommend it for usage.&lt;br /&gt;
&lt;br /&gt;
=== Six ===&lt;br /&gt;
&lt;br /&gt;
[https://pythonhosted.org/six/ Six] was the first library developed to simplify Python 2 to 3 migration. It provides a set of wrappers that hide differences between Python 2 and 3 behind its API. It is less intrusive than the following alternative because it does not monkey-patch built-in names, but in order to use Six library effectively you need to learn its API. Six can be used both for writing new Python 2/3-compatible addons and converting existing ones, but it requires good knowledge of Python 2/3 differences to pick necessary Six features that address specific differences.&lt;br /&gt;
&lt;br /&gt;
Six library is included in the Kodi addon repository as &#039;&#039;&#039;script.module.six addon&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Future ===&lt;br /&gt;
&lt;br /&gt;
[http://python-future.org/ Future] library, like Six, was created to simplify porting existing Python 2 code to 3. But it uses a different approach than Six. Future monkey-patches built-in Python objects to make Python 2 behave like Python 3. The advantage of such approach is that code written using Future is close to idiomatic Python 3 and requires little re-work if you decide to drop Python 2 support in the future. However, such approach may cause problems in some rare edge-cases.&lt;br /&gt;
&lt;br /&gt;
Future library also includes &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; command-line utility for converting existing Python 2 code to 2/3-compatible and in my experiments this utility showed good results.&lt;br /&gt;
Future library (without additional utilities) is included in the Kodi addon repository as script.module.future addon.&lt;br /&gt;
&lt;br /&gt;
=== PyCharm ===&lt;br /&gt;
&lt;br /&gt;
PyCharm, except for being a really good Python IDE, also provides code compatibility inspection that helps you write Python 2/3-portable code. Open &#039;&#039;&#039;Settings&#039;&#039;&#039; (Alt+F7) &amp;gt; &#039;&#039;&#039;Editor&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Inspections&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Python&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Code compatibility inspections&#039;&#039;&#039; and check Python version that you want to support.&lt;br /&gt;
&lt;br /&gt;
PyCharm Community Edition is free and provides all features you need for creating Python addons for Kodi.&lt;br /&gt;
&lt;br /&gt;
== Writing Portable Code ==&lt;br /&gt;
&lt;br /&gt;
Here I’ll give you some tips about how to write portable code:&lt;br /&gt;
&lt;br /&gt;
* Learn the differences between Python 2 and 3. You need to know at least the most important differences between the two major Python versions.&lt;br /&gt;
&lt;br /&gt;
* Use version control system — git or mercurial — to track changes in your code. If you are porting existing code, do it in a separate branch.&lt;br /&gt;
&lt;br /&gt;
* No matter if you are going to write a brand new addon or to port existing addon to Python 3, carefully choose your tools. It is totally possible to write portable code without any helper tools and libraries, but you need to know what you are doing. However, in most cases I’d recommend you to use Future library and its utilities. Carefully read Future documentation.&lt;br /&gt;
&lt;br /&gt;
* Put the following line at the beginning of all your modules:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will enable respective Python 3 features in your code. You don’t need to import print_function (another Python 3 feature) because in Kodi addons you should to use xbmc.log() to write messages to the Kodi log file.&lt;br /&gt;
&lt;br /&gt;
=== Writing New Addons ===&lt;br /&gt;
&lt;br /&gt;
Check the [http://python-future.org/quickstart.html#if-you-are-writing-code-from-scratch Quick Start Guide] section of Future library documentation. You can also use Six library, but, as it was said previously, you need to learn its API to pick the necessary features to address specific Python version differences, while Future allows to write your code in (almost) idiomatic Python 3.&lt;br /&gt;
&lt;br /&gt;
A brief procedure for writing new Python 2/3-compatible addons with Future library:&lt;br /&gt;
&lt;br /&gt;
# Create a new virtual environment with Python 3 interpreter and activate it.&lt;br /&gt;
# Install Future library: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Point your IDE (Integrated Development Environment) to that environment. For example, in PyCharm: &#039;&#039;&#039;File&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Setting&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project Interpreter&#039;&#039;&#039;.&lt;br /&gt;
# Put the following line at the beginning of your Python code:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
from future import standard_library&lt;br /&gt;
from future.builtins import *&lt;br /&gt;
standard_library.install_aliases()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Write your addon using Python 3 syntax and standard library names. However, you may still need to use wrappers from Future library for some specific cases (e.g. iterators over &amp;lt;code&amp;gt;dict&amp;lt;/code&amp;gt; elements). Read Future docs for more info.&lt;br /&gt;
&lt;br /&gt;
=== Porting Existing Addons ===&lt;br /&gt;
&lt;br /&gt;
A brief procedure for porting existing code to Python 3-compatible with Future library:&lt;br /&gt;
&lt;br /&gt;
# Install Future library into your working Python 2 virtual environment: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; utility to convert all your scripts and modules to portable code.&lt;br /&gt;
&lt;br /&gt;
Test your new or converted addon in Kodi with Python 2 interpreter and fix all found issues. After that test the addon in Kodi with Python 3 interpreter and again fix all found issues.&lt;br /&gt;
You can use [https://github.com/romanvm/kodi.web-pdb Web-PDB] debugger for troubleshooting issues in your code. It is compatible with both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* Python 2 and 3 differences: https://docs.python.org/3.6/whatsnew/3.0.html&lt;br /&gt;
* Future library documentation: http://python-future.org/&lt;br /&gt;
* Six library documentation: https://pythonhosted.org/six/&lt;br /&gt;
* Kodi test builds with Python 3 for Windows: http://mirrors.xbmc.org/test-builds/windows/win32/&lt;br /&gt;
* Kodi test builds with Python 3 for Linux Ubuntu: https://launchpad.net/~wsnipex/+archive/ubuntu/kodi-python3/+packages&lt;br /&gt;
* “Python 3 migration” section on the Kodi official forum: https://forum.kodi.tv/forumdisplay.php?fid=281&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132478</id>
		<title>General information about migration to Python 3</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132478"/>
		<updated>2018-01-19T09:57:16Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: /* Writing New Addons */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Python 3 was released 9 years ago and EOL for Python 2.7 is scheduled for 2020. Currently more and more Python project are switching to Python 3 or 2/3 compatible code. The issue of migrating Kodi’s built-in Python interpreter to Python 3.x was brought up on the Kodi forum several times. Now, thanks to a successful GSOC 2017 project, we have a working Python 3 interpreter for Kodi. That is why on Kodi DevCon 2017 Team Kodi decided that we will switch to Python 3 in the future Kodi release (v.19 preliminarily).&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 3.x versions are not backward-compatible with Python 2.x, so we decided to urge addon developers to start porting their addons to Python 3 by making the addons compatible with both Python 2 and 3 and submitting them to the official repo. This way, when Kodi with Python 3 is released, we won’t have a situation when we have no working addons.&lt;br /&gt;
&lt;br /&gt;
== The Process ==&lt;br /&gt;
&lt;br /&gt;
* Starting from Kodi 18 (Leia), only addons that are compatible with both Python 2 and 3 will be accepted to the official addon repository.&lt;br /&gt;
* We will provide Kodi builds with Python 3 so that addon developers can tests if their addons are really compatible with Python 3.&lt;br /&gt;
* A thread will be created on the Kodi forum so that addon devs can get help with their migration process.&lt;br /&gt;
&lt;br /&gt;
== Python 3 And 2 Differences ==&lt;br /&gt;
&lt;br /&gt;
Below is a brief overview of the main differences between Python 3 and 2.&lt;br /&gt;
&lt;br /&gt;
=== Unicode strings by default ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 built-in &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds the sequence of bytes so it can be used to store both binary data and textual data in ASCII or any of 8-bit fixed-length encodings (there were plenty). Python 2 also has &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; type that can store text in various writing systems. A minimal unit of a &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; object is a Unicode codepoint (a Unicode character). Both &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects can be mixed and matched together, for example, concatenated using &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; operator.&lt;br /&gt;
&lt;br /&gt;
In Python 3 &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds Unicode characters, and for binary data a new &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; type was added. This type was also added to Python 2.7 to simplify porting to Python 3 but in Python 2.7 bytes is simply an alias for &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; types are incompatible, and an attempt to use both together will result in &amp;lt;code&amp;gt;TypeError&amp;lt;/code&amp;gt; exception. A &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; object can be converted to &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; using .decode() method, and a &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; is converted to &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; using .encode() method.&lt;br /&gt;
&lt;br /&gt;
=== Absolute Import ===&lt;br /&gt;
Python 3 uses so called “absolute import” and you can no longer import modules from inside a package using only a module name. You need to either to use either a fully qualified name or a “dotted” notation.&lt;br /&gt;
&lt;br /&gt;
Let’s assume that you have a foo package that contains bar and spam modules, and you need to import bar module from spam. In Python 2 you can do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But in Python 3 you need to use either&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import foo.bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from . import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating Point Division ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 applying division operator to int numbers produces int result. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 / 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Python 3 division operator always gives you a float result.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4/3&lt;br /&gt;
1.3333333333333333&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get an int result you need to use integer division operator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 // 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Print Function ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 print statement has been replaced with print() function. This is not very relevant to Kodi because using print in Python addons is discouraged and xbmc.log() function should be used to write messages to the Kodi log.&lt;br /&gt;
&lt;br /&gt;
=== Default Iterators ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 most function and methods that produce sequences return iterators instead of lists. For example, range() function and .items(), .keys(), .values() of dict type produce iterators instead of lists, and their Python 2 analogues — xrange() function and .iter* methods of dict type — have been removed.&lt;br /&gt;
&lt;br /&gt;
=== No long Integers ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 long integer type has been removed and int type can now hold a number of arbitrary length.&lt;br /&gt;
&lt;br /&gt;
Those are only some of the differences between Python 2 and 3. For a more complete list see [https://docs.python.org/3.6/whatsnew/3.0.html official Python documentation].&lt;br /&gt;
&lt;br /&gt;
== Some Useful Information ==&lt;br /&gt;
&lt;br /&gt;
As it was said above, Python 3 includes a number of incompatible changes, so to avoid situation when after upgrading Kodi for Python 3 support most Python addons will be broken developers should start to port their addons to be compatible with both Python 2 and 3. This is not a trivial task but fortunately there are a number of tools and recommendations to simplify this process. Here I’ll give you some advice and information about tools that will simplify creating portable code that runs on both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
=== Know Your Strings! ===&lt;br /&gt;
&lt;br /&gt;
This is the most problematic part of porting Python 2 code to Python 3 so I put it first. One of the most notable differences between Python 2 and 3 is clear separation between “textual” and “binary” strings, that is, between textual data and their binary representation. This difference is often difficult to understand, especially for novice developers (not only in Python), and the fact that in Python 2 you can mix together str (binary data) and unicode (textual data) adds to that difficulty.&lt;br /&gt;
&lt;br /&gt;
There are many explanations in the Internet, but here are the most basic things about strings that you need to know:&lt;br /&gt;
&lt;br /&gt;
“Textual” or Unicode strings (unicode in Python 2 and str in Python 3) hold text as a sequence of characters. A minimal unit in such strings is a Unicode character — an abstract entity that represent an alphabet symbol, a punctuation sign or other symbol included in the Unicode character table. Of course, such symbols have concrete internal binary representation (a computer is a binary machine after all), but this representation is not relevant to us. All you need to know is that “textual” strings contain text units without being tied to concrete binary representation.&lt;br /&gt;
&lt;br /&gt;
Unlike Unicode strings, binary strings (str in Python 2 and bytes in both Python 2 and 3) hold binary data, and a minimal unit of such strings is a byte or 8 bits. Historically, in Python 2 such strings are used for textual data encoded in ASCII or other 1-byte fixed-length encoding (e.g. Windows 1251 for Cyrillic alphabets). However, this approach has its limitation, that is why unicode type was introduced in Python 2, and in Python 3 it was renamed to str and made a default container for textual data.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 2 allows to mix and match Unicode and binary strings in the same context and this creates big problems when porting Python 2 code to Python 3. So in order to successfully port your code to Python 3 you need to carefully consider how textual data are processed in your addon. The following recommendations will help you avoid problems when writing Python 2/3 compatible code.&lt;br /&gt;
&lt;br /&gt;
=== Avoid using binary strings for text ===&lt;br /&gt;
&lt;br /&gt;
Store all your text as Unicode strings. This means that all binary strings received from external sources (textual files, websites, various APIs) need to be decoded using appropriate encoding (UTF-8 in most cases). If you need to use strings literals (although using hardcoded strings for user-facing text in Kodi is strongly discouraged), they need to be defined as unicode strings as well. You can use either&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
at the beginning of your modules to enable unicode strings by default as in Python 3 or u-strings, e.g. &amp;lt;code&amp;gt;u&#039;foo&#039;&amp;lt;/code&amp;gt; (Python 3 understands them too) — it doesn&#039;t really matter as long as you are doing it consistently.&lt;br /&gt;
&lt;br /&gt;
=== Know the libraries you are using ===&lt;br /&gt;
Working with Python Standard Library and third-party libraries (including Kodi Python API) you should know that types their functions and methods expect and what types they return. For example, in popular requests library Response.text property returns a Unicode string and Response.content returns a binary string.&lt;br /&gt;
&lt;br /&gt;
If a function/method/property returns a binary string, you need to decode it to a Unicode string using .decode() method. Don’t use unicode class constructor because unicode type does not exist in Python 3.&lt;br /&gt;
&lt;br /&gt;
If you are reading textual files from disk, it is better to use io.open() instead of built-in open(). io.open() can decode file contents to Unicode using specified encoding and works identically both in Python 2 and 3. Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import io&lt;br /&gt;
&lt;br /&gt;
with io.open(&#039;foo.txt&#039;, &#039;r&#039;, encoding=&#039;utf-8&#039;) as fo:&lt;br /&gt;
   text = fo.read()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Potential pitfalls ===&lt;br /&gt;
&lt;br /&gt;
When writing Python 2/3-compatible code or converting existing Python 2 codebase to compatible code you should pay attention to the following Python language constructions where TypeError exceptions may happen because of incompatible string types if you don’t get your strings in order:&lt;br /&gt;
&lt;br /&gt;
* String concatenations with + operator (&amp;lt;code&amp;gt;&#039;foo&#039; + &#039;bar&#039;&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String formatting — both “old style” (&amp;lt;code&amp;gt;&#039;foo %s&#039; % &#039;bar&#039;&amp;lt;/code&amp;gt;) and “new style” (&amp;lt;code&amp;gt;&#039;foo {}&#039;.format(&#039;bar&#039;)&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String joining (&amp;lt;code&amp;gt;&#039;, &#039;.join([&#039;foo&#039;, &#039;bar&#039;])&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
In all those cases always make sure that you work with Unicode strings only.&lt;br /&gt;
Another source of subtle bugs is functions and methods that accept and return binary strings (str type) in Python 2  but Unicode strings in Python 3 (again, str type but with different properties). You can use the following utility functions to “normalize” strings that are provided to such functions/methods and received from them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
__all__ = [&#039;PY2&#039;, &#039;py2_encode&#039;, &#039;py2_decode&#039;]&lt;br /&gt;
&lt;br /&gt;
PY2 = sys.version_info[0] == 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_encode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Encode Python 2 ``unicode`` to ``str``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.   &lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, unicode):&lt;br /&gt;
       s = s.encode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_decode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Decode Python 2 ``str`` to ``unicode``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, str):&lt;br /&gt;
       s = s.decode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Helper Libraries and Tools ==&lt;br /&gt;
&lt;br /&gt;
=== 2to3 ===&lt;br /&gt;
&lt;br /&gt;
[https://docs.python.org/2/library/2to3.html 2to3] script is created by Python developers to help converting existing Python 2 code to Python 3. On Windows it is included in Python distribution (Tools subfolder) but on other OSes you man need to install it separately. For example, on Ubuntu it is included in python-examples package. Note that this script is created for conversion from Python 2 to 3, not for writing portable code, so you need to treat its output with care.&lt;br /&gt;
&lt;br /&gt;
=== Modernize ===&lt;br /&gt;
&lt;br /&gt;
https://python-modernize.readthedocs.io/en/latest/ Modernize] script works on top of 2to3 and is supposed to help you to convert your existing Python 2 code to Python 2/3-compatible. However, in my experiments it did not work reliably even in simple cases so I cannot recommend it for usage.&lt;br /&gt;
&lt;br /&gt;
=== Six ===&lt;br /&gt;
&lt;br /&gt;
[https://pythonhosted.org/six/ Six] was the first library developed to simplify Python 2 to 3 migration. It provides a set of wrappers that hide differences between Python 2 and 3 behind its API. It is less intrusive than the following alternative because it does not monkey-patch built-in names, but in order to use Six library effectively you need to learn its API. Six can be used both for writing new Python 2/3-compatible addons and converting existing ones, but it requires good knowledge of Python 2/3 differences to pick necessary Six features that address specific differences.&lt;br /&gt;
&lt;br /&gt;
Six library is included in the Kodi addon repository as &#039;&#039;&#039;script.module.six addon&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Future ===&lt;br /&gt;
&lt;br /&gt;
[http://python-future.org/ Future] library, like Six, was created to simplify porting existing Python 2 code to 3. But it uses a different approach than Six. Future monkey-patches built-in Python objects to make Python 2 behave like Python 3. The advantage of such approach is that code written using Future is close to idiomatic Python 3 and requires little re-work if you decide to drop Python 2 support in the future. However, such approach may cause problems in some rare edge-cases.&lt;br /&gt;
&lt;br /&gt;
Future library also includes &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; command-line utility for converting existing Python 2 code to 2/3-compatible and in my experiments this utility showed good results.&lt;br /&gt;
Future library (without additional utilities) is included in the Kodi addon repository as script.module.future addon.&lt;br /&gt;
&lt;br /&gt;
=== PyCharm ===&lt;br /&gt;
&lt;br /&gt;
PyCharm, except for being a really good Python IDE, also provides code compatibility inspection that helps you write Python 2/3-portable code. Open &#039;&#039;&#039;Settings&#039;&#039;&#039; (Alt+F7) &amp;gt; &#039;&#039;&#039;Editor&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Inspections&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Python&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Code compatibility inspections&#039;&#039;&#039; and check Python version that you want to support.&lt;br /&gt;
&lt;br /&gt;
PyCharm Community Edition is free and provides all features you need for creating Python addons for Kodi.&lt;br /&gt;
&lt;br /&gt;
== Writing Portable Code ==&lt;br /&gt;
&lt;br /&gt;
Here I’ll give you some tips about how to write portable code:&lt;br /&gt;
&lt;br /&gt;
* Learn the differences between Python 2 and 3. You need to know at least the most important differences between the two major Python versions.&lt;br /&gt;
&lt;br /&gt;
* Use version control system — git or mercurial — to track changes in your code. If you are porting existing code, do it in a separate branch.&lt;br /&gt;
&lt;br /&gt;
* No matter if you are going to write a brand new addon or to port existing addon to Python 3, carefully choose your tools. It is totally possible to write portable code without any helper tools and libraries, but you need to know what you are doing. However, in most cases I’d recommend you to use Future library and its utilities. Carefully read Future documentation.&lt;br /&gt;
&lt;br /&gt;
* Put the following line at the beginning of all your modules:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will enable respective Python 3 features in your code. You don’t need to import print_function (another Python 3 feature) because in Kodi addons you should to use xbmc.log() to write messages to the Kodi log file.&lt;br /&gt;
&lt;br /&gt;
=== Writing New Addons ===&lt;br /&gt;
&lt;br /&gt;
Check the [http://python-future.org/quickstart.html#if-you-are-writing-code-from-scratch Quick Start Guide] section of Future library documentation. You can also use Six library, but, as it was said previously, you need to learn its API to pick the necessary features to address specific Python version differences, while Future allows to write your code in (almost) idiomatic Python 3.&lt;br /&gt;
&lt;br /&gt;
A brief procedure for writing new Python 2/3-compatible addons with Future library:&lt;br /&gt;
&lt;br /&gt;
# Create a new virtual environment with Python 3 interpreter and activate it.&lt;br /&gt;
# Install Future library: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Point your IDE (Integrated Development Environment) to that environment. For example, in PyCharm: &#039;&#039;&#039;File&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Setting&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project Interpreter&#039;&#039;&#039;.&lt;br /&gt;
# Put the following line at the beginning of your Python code:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
from future import standard_library&lt;br /&gt;
from future.builtins import *&lt;br /&gt;
standard_library.install_aliases()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Write your addon using Python 3 syntax and standard library names. However, you may still need to use wrappers from Future library for some specific cases (e.g. iterators over &amp;lt;code&amp;gt;dict&amp;lt;/code&amp;gt; elements. Read Future docs for more info.&lt;br /&gt;
&lt;br /&gt;
=== Porting Existing Addons ===&lt;br /&gt;
&lt;br /&gt;
A brief procedure for porting existing code to Python 3-compatible with Future library:&lt;br /&gt;
&lt;br /&gt;
# Install Future library into your working Python 2 virtual environment: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; utility to convert all your scripts and modules to portable code.&lt;br /&gt;
&lt;br /&gt;
Test your new or converted addon in Kodi with Python 2 interpreter and fix all found issues. After that test the addon in Kodi with Python 3 interpreter and again fix all found issues.&lt;br /&gt;
You can use [https://github.com/romanvm/kodi.web-pdb Web-PDB] debugger for troubleshooting issues in your code. It is compatible with both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* Python 2 and 3 differences: https://docs.python.org/3.6/whatsnew/3.0.html&lt;br /&gt;
* Future library documentation: http://python-future.org/&lt;br /&gt;
* Six library documentation: https://pythonhosted.org/six/&lt;br /&gt;
* Kodi test builds with Python 3 for Windows: http://mirrors.xbmc.org/test-builds/windows/win32/&lt;br /&gt;
* Kodi test builds with Python 3 for Linux Ubuntu: https://launchpad.net/~wsnipex/+archive/ubuntu/kodi-python3/+packages&lt;br /&gt;
* “Python 3 migration” section on the Kodi official forum: https://forum.kodi.tv/forumdisplay.php?fid=281&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132477</id>
		<title>General information about migration to Python 3</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132477"/>
		<updated>2018-01-19T09:56:56Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: /* Writing New Addons */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Python 3 was released 9 years ago and EOL for Python 2.7 is scheduled for 2020. Currently more and more Python project are switching to Python 3 or 2/3 compatible code. The issue of migrating Kodi’s built-in Python interpreter to Python 3.x was brought up on the Kodi forum several times. Now, thanks to a successful GSOC 2017 project, we have a working Python 3 interpreter for Kodi. That is why on Kodi DevCon 2017 Team Kodi decided that we will switch to Python 3 in the future Kodi release (v.19 preliminarily).&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 3.x versions are not backward-compatible with Python 2.x, so we decided to urge addon developers to start porting their addons to Python 3 by making the addons compatible with both Python 2 and 3 and submitting them to the official repo. This way, when Kodi with Python 3 is released, we won’t have a situation when we have no working addons.&lt;br /&gt;
&lt;br /&gt;
== The Process ==&lt;br /&gt;
&lt;br /&gt;
* Starting from Kodi 18 (Leia), only addons that are compatible with both Python 2 and 3 will be accepted to the official addon repository.&lt;br /&gt;
* We will provide Kodi builds with Python 3 so that addon developers can tests if their addons are really compatible with Python 3.&lt;br /&gt;
* A thread will be created on the Kodi forum so that addon devs can get help with their migration process.&lt;br /&gt;
&lt;br /&gt;
== Python 3 And 2 Differences ==&lt;br /&gt;
&lt;br /&gt;
Below is a brief overview of the main differences between Python 3 and 2.&lt;br /&gt;
&lt;br /&gt;
=== Unicode strings by default ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 built-in &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds the sequence of bytes so it can be used to store both binary data and textual data in ASCII or any of 8-bit fixed-length encodings (there were plenty). Python 2 also has &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; type that can store text in various writing systems. A minimal unit of a &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; object is a Unicode codepoint (a Unicode character). Both &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects can be mixed and matched together, for example, concatenated using &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; operator.&lt;br /&gt;
&lt;br /&gt;
In Python 3 &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds Unicode characters, and for binary data a new &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; type was added. This type was also added to Python 2.7 to simplify porting to Python 3 but in Python 2.7 bytes is simply an alias for &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; types are incompatible, and an attempt to use both together will result in &amp;lt;code&amp;gt;TypeError&amp;lt;/code&amp;gt; exception. A &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; object can be converted to &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; using .decode() method, and a &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; is converted to &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; using .encode() method.&lt;br /&gt;
&lt;br /&gt;
=== Absolute Import ===&lt;br /&gt;
Python 3 uses so called “absolute import” and you can no longer import modules from inside a package using only a module name. You need to either to use either a fully qualified name or a “dotted” notation.&lt;br /&gt;
&lt;br /&gt;
Let’s assume that you have a foo package that contains bar and spam modules, and you need to import bar module from spam. In Python 2 you can do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But in Python 3 you need to use either&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import foo.bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from . import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating Point Division ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 applying division operator to int numbers produces int result. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 / 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Python 3 division operator always gives you a float result.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4/3&lt;br /&gt;
1.3333333333333333&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get an int result you need to use integer division operator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 // 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Print Function ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 print statement has been replaced with print() function. This is not very relevant to Kodi because using print in Python addons is discouraged and xbmc.log() function should be used to write messages to the Kodi log.&lt;br /&gt;
&lt;br /&gt;
=== Default Iterators ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 most function and methods that produce sequences return iterators instead of lists. For example, range() function and .items(), .keys(), .values() of dict type produce iterators instead of lists, and their Python 2 analogues — xrange() function and .iter* methods of dict type — have been removed.&lt;br /&gt;
&lt;br /&gt;
=== No long Integers ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 long integer type has been removed and int type can now hold a number of arbitrary length.&lt;br /&gt;
&lt;br /&gt;
Those are only some of the differences between Python 2 and 3. For a more complete list see [https://docs.python.org/3.6/whatsnew/3.0.html official Python documentation].&lt;br /&gt;
&lt;br /&gt;
== Some Useful Information ==&lt;br /&gt;
&lt;br /&gt;
As it was said above, Python 3 includes a number of incompatible changes, so to avoid situation when after upgrading Kodi for Python 3 support most Python addons will be broken developers should start to port their addons to be compatible with both Python 2 and 3. This is not a trivial task but fortunately there are a number of tools and recommendations to simplify this process. Here I’ll give you some advice and information about tools that will simplify creating portable code that runs on both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
=== Know Your Strings! ===&lt;br /&gt;
&lt;br /&gt;
This is the most problematic part of porting Python 2 code to Python 3 so I put it first. One of the most notable differences between Python 2 and 3 is clear separation between “textual” and “binary” strings, that is, between textual data and their binary representation. This difference is often difficult to understand, especially for novice developers (not only in Python), and the fact that in Python 2 you can mix together str (binary data) and unicode (textual data) adds to that difficulty.&lt;br /&gt;
&lt;br /&gt;
There are many explanations in the Internet, but here are the most basic things about strings that you need to know:&lt;br /&gt;
&lt;br /&gt;
“Textual” or Unicode strings (unicode in Python 2 and str in Python 3) hold text as a sequence of characters. A minimal unit in such strings is a Unicode character — an abstract entity that represent an alphabet symbol, a punctuation sign or other symbol included in the Unicode character table. Of course, such symbols have concrete internal binary representation (a computer is a binary machine after all), but this representation is not relevant to us. All you need to know is that “textual” strings contain text units without being tied to concrete binary representation.&lt;br /&gt;
&lt;br /&gt;
Unlike Unicode strings, binary strings (str in Python 2 and bytes in both Python 2 and 3) hold binary data, and a minimal unit of such strings is a byte or 8 bits. Historically, in Python 2 such strings are used for textual data encoded in ASCII or other 1-byte fixed-length encoding (e.g. Windows 1251 for Cyrillic alphabets). However, this approach has its limitation, that is why unicode type was introduced in Python 2, and in Python 3 it was renamed to str and made a default container for textual data.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 2 allows to mix and match Unicode and binary strings in the same context and this creates big problems when porting Python 2 code to Python 3. So in order to successfully port your code to Python 3 you need to carefully consider how textual data are processed in your addon. The following recommendations will help you avoid problems when writing Python 2/3 compatible code.&lt;br /&gt;
&lt;br /&gt;
=== Avoid using binary strings for text ===&lt;br /&gt;
&lt;br /&gt;
Store all your text as Unicode strings. This means that all binary strings received from external sources (textual files, websites, various APIs) need to be decoded using appropriate encoding (UTF-8 in most cases). If you need to use strings literals (although using hardcoded strings for user-facing text in Kodi is strongly discouraged), they need to be defined as unicode strings as well. You can use either&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
at the beginning of your modules to enable unicode strings by default as in Python 3 or u-strings, e.g. &amp;lt;code&amp;gt;u&#039;foo&#039;&amp;lt;/code&amp;gt; (Python 3 understands them too) — it doesn&#039;t really matter as long as you are doing it consistently.&lt;br /&gt;
&lt;br /&gt;
=== Know the libraries you are using ===&lt;br /&gt;
Working with Python Standard Library and third-party libraries (including Kodi Python API) you should know that types their functions and methods expect and what types they return. For example, in popular requests library Response.text property returns a Unicode string and Response.content returns a binary string.&lt;br /&gt;
&lt;br /&gt;
If a function/method/property returns a binary string, you need to decode it to a Unicode string using .decode() method. Don’t use unicode class constructor because unicode type does not exist in Python 3.&lt;br /&gt;
&lt;br /&gt;
If you are reading textual files from disk, it is better to use io.open() instead of built-in open(). io.open() can decode file contents to Unicode using specified encoding and works identically both in Python 2 and 3. Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import io&lt;br /&gt;
&lt;br /&gt;
with io.open(&#039;foo.txt&#039;, &#039;r&#039;, encoding=&#039;utf-8&#039;) as fo:&lt;br /&gt;
   text = fo.read()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Potential pitfalls ===&lt;br /&gt;
&lt;br /&gt;
When writing Python 2/3-compatible code or converting existing Python 2 codebase to compatible code you should pay attention to the following Python language constructions where TypeError exceptions may happen because of incompatible string types if you don’t get your strings in order:&lt;br /&gt;
&lt;br /&gt;
* String concatenations with + operator (&amp;lt;code&amp;gt;&#039;foo&#039; + &#039;bar&#039;&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String formatting — both “old style” (&amp;lt;code&amp;gt;&#039;foo %s&#039; % &#039;bar&#039;&amp;lt;/code&amp;gt;) and “new style” (&amp;lt;code&amp;gt;&#039;foo {}&#039;.format(&#039;bar&#039;)&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String joining (&amp;lt;code&amp;gt;&#039;, &#039;.join([&#039;foo&#039;, &#039;bar&#039;])&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
In all those cases always make sure that you work with Unicode strings only.&lt;br /&gt;
Another source of subtle bugs is functions and methods that accept and return binary strings (str type) in Python 2  but Unicode strings in Python 3 (again, str type but with different properties). You can use the following utility functions to “normalize” strings that are provided to such functions/methods and received from them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
__all__ = [&#039;PY2&#039;, &#039;py2_encode&#039;, &#039;py2_decode&#039;]&lt;br /&gt;
&lt;br /&gt;
PY2 = sys.version_info[0] == 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_encode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Encode Python 2 ``unicode`` to ``str``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.   &lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, unicode):&lt;br /&gt;
       s = s.encode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_decode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Decode Python 2 ``str`` to ``unicode``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, str):&lt;br /&gt;
       s = s.decode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Helper Libraries and Tools ==&lt;br /&gt;
&lt;br /&gt;
=== 2to3 ===&lt;br /&gt;
&lt;br /&gt;
[https://docs.python.org/2/library/2to3.html 2to3] script is created by Python developers to help converting existing Python 2 code to Python 3. On Windows it is included in Python distribution (Tools subfolder) but on other OSes you man need to install it separately. For example, on Ubuntu it is included in python-examples package. Note that this script is created for conversion from Python 2 to 3, not for writing portable code, so you need to treat its output with care.&lt;br /&gt;
&lt;br /&gt;
=== Modernize ===&lt;br /&gt;
&lt;br /&gt;
https://python-modernize.readthedocs.io/en/latest/ Modernize] script works on top of 2to3 and is supposed to help you to convert your existing Python 2 code to Python 2/3-compatible. However, in my experiments it did not work reliably even in simple cases so I cannot recommend it for usage.&lt;br /&gt;
&lt;br /&gt;
=== Six ===&lt;br /&gt;
&lt;br /&gt;
[https://pythonhosted.org/six/ Six] was the first library developed to simplify Python 2 to 3 migration. It provides a set of wrappers that hide differences between Python 2 and 3 behind its API. It is less intrusive than the following alternative because it does not monkey-patch built-in names, but in order to use Six library effectively you need to learn its API. Six can be used both for writing new Python 2/3-compatible addons and converting existing ones, but it requires good knowledge of Python 2/3 differences to pick necessary Six features that address specific differences.&lt;br /&gt;
&lt;br /&gt;
Six library is included in the Kodi addon repository as &#039;&#039;&#039;script.module.six addon&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Future ===&lt;br /&gt;
&lt;br /&gt;
[http://python-future.org/ Future] library, like Six, was created to simplify porting existing Python 2 code to 3. But it uses a different approach than Six. Future monkey-patches built-in Python objects to make Python 2 behave like Python 3. The advantage of such approach is that code written using Future is close to idiomatic Python 3 and requires little re-work if you decide to drop Python 2 support in the future. However, such approach may cause problems in some rare edge-cases.&lt;br /&gt;
&lt;br /&gt;
Future library also includes &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; command-line utility for converting existing Python 2 code to 2/3-compatible and in my experiments this utility showed good results.&lt;br /&gt;
Future library (without additional utilities) is included in the Kodi addon repository as script.module.future addon.&lt;br /&gt;
&lt;br /&gt;
=== PyCharm ===&lt;br /&gt;
&lt;br /&gt;
PyCharm, except for being a really good Python IDE, also provides code compatibility inspection that helps you write Python 2/3-portable code. Open &#039;&#039;&#039;Settings&#039;&#039;&#039; (Alt+F7) &amp;gt; &#039;&#039;&#039;Editor&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Inspections&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Python&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Code compatibility inspections&#039;&#039;&#039; and check Python version that you want to support.&lt;br /&gt;
&lt;br /&gt;
PyCharm Community Edition is free and provides all features you need for creating Python addons for Kodi.&lt;br /&gt;
&lt;br /&gt;
== Writing Portable Code ==&lt;br /&gt;
&lt;br /&gt;
Here I’ll give you some tips about how to write portable code:&lt;br /&gt;
&lt;br /&gt;
* Learn the differences between Python 2 and 3. You need to know at least the most important differences between the two major Python versions.&lt;br /&gt;
&lt;br /&gt;
* Use version control system — git or mercurial — to track changes in your code. If you are porting existing code, do it in a separate branch.&lt;br /&gt;
&lt;br /&gt;
* No matter if you are going to write a brand new addon or to port existing addon to Python 3, carefully choose your tools. It is totally possible to write portable code without any helper tools and libraries, but you need to know what you are doing. However, in most cases I’d recommend you to use Future library and its utilities. Carefully read Future documentation.&lt;br /&gt;
&lt;br /&gt;
* Put the following line at the beginning of all your modules:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will enable respective Python 3 features in your code. You don’t need to import print_function (another Python 3 feature) because in Kodi addons you should to use xbmc.log() to write messages to the Kodi log file.&lt;br /&gt;
&lt;br /&gt;
=== Writing New Addons ===&lt;br /&gt;
&lt;br /&gt;
Check the [http://python-future.org/quickstart.html#if-you-are-writing-code-from-scratch Quick Start Guide] section of Future library documentation. You can also use Six library, but, as it was said previously, you need to learn its API to pick the necessary features to address specific Python version differences, while Future allows to write your code in (almost) idiomatic Python 3.&lt;br /&gt;
&lt;br /&gt;
A brief procedure for writing new Python 2/3-compatible addons with Future library:&lt;br /&gt;
&lt;br /&gt;
# Create a new virtual environment with Python 3 interpreter and activate it.&lt;br /&gt;
# Install Future library: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Point your IDE (Integrated Development Environment) to that environment. For example, in PyCharm: &#039;&#039;&#039;File&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Setting&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project Interpreter&#039;&#039;&#039;.&lt;br /&gt;
# Put the following line at the beginning of your Python code:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
from future import standard_library&lt;br /&gt;
from future.builtins import *&lt;br /&gt;
standard_library.install_aliases()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Write your addon using Python 3 syntax and standard library names. However, you may still need to use wrappers from Future library for some specific cases (e.g. iterators over &amp;lt;code&amp;gt;dict&amp;lt;/dict&amp;gt; elements. Read Future docs for more info.&lt;br /&gt;
&lt;br /&gt;
=== Porting Existing Addons ===&lt;br /&gt;
&lt;br /&gt;
A brief procedure for porting existing code to Python 3-compatible with Future library:&lt;br /&gt;
&lt;br /&gt;
# Install Future library into your working Python 2 virtual environment: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; utility to convert all your scripts and modules to portable code.&lt;br /&gt;
&lt;br /&gt;
Test your new or converted addon in Kodi with Python 2 interpreter and fix all found issues. After that test the addon in Kodi with Python 3 interpreter and again fix all found issues.&lt;br /&gt;
You can use [https://github.com/romanvm/kodi.web-pdb Web-PDB] debugger for troubleshooting issues in your code. It is compatible with both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* Python 2 and 3 differences: https://docs.python.org/3.6/whatsnew/3.0.html&lt;br /&gt;
* Future library documentation: http://python-future.org/&lt;br /&gt;
* Six library documentation: https://pythonhosted.org/six/&lt;br /&gt;
* Kodi test builds with Python 3 for Windows: http://mirrors.xbmc.org/test-builds/windows/win32/&lt;br /&gt;
* Kodi test builds with Python 3 for Linux Ubuntu: https://launchpad.net/~wsnipex/+archive/ubuntu/kodi-python3/+packages&lt;br /&gt;
* “Python 3 migration” section on the Kodi official forum: https://forum.kodi.tv/forumdisplay.php?fid=281&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132476</id>
		<title>General information about migration to Python 3</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132476"/>
		<updated>2018-01-19T09:55:38Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: /* Writing New Addons */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Python 3 was released 9 years ago and EOL for Python 2.7 is scheduled for 2020. Currently more and more Python project are switching to Python 3 or 2/3 compatible code. The issue of migrating Kodi’s built-in Python interpreter to Python 3.x was brought up on the Kodi forum several times. Now, thanks to a successful GSOC 2017 project, we have a working Python 3 interpreter for Kodi. That is why on Kodi DevCon 2017 Team Kodi decided that we will switch to Python 3 in the future Kodi release (v.19 preliminarily).&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 3.x versions are not backward-compatible with Python 2.x, so we decided to urge addon developers to start porting their addons to Python 3 by making the addons compatible with both Python 2 and 3 and submitting them to the official repo. This way, when Kodi with Python 3 is released, we won’t have a situation when we have no working addons.&lt;br /&gt;
&lt;br /&gt;
== The Process ==&lt;br /&gt;
&lt;br /&gt;
* Starting from Kodi 18 (Leia), only addons that are compatible with both Python 2 and 3 will be accepted to the official addon repository.&lt;br /&gt;
* We will provide Kodi builds with Python 3 so that addon developers can tests if their addons are really compatible with Python 3.&lt;br /&gt;
* A thread will be created on the Kodi forum so that addon devs can get help with their migration process.&lt;br /&gt;
&lt;br /&gt;
== Python 3 And 2 Differences ==&lt;br /&gt;
&lt;br /&gt;
Below is a brief overview of the main differences between Python 3 and 2.&lt;br /&gt;
&lt;br /&gt;
=== Unicode strings by default ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 built-in &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds the sequence of bytes so it can be used to store both binary data and textual data in ASCII or any of 8-bit fixed-length encodings (there were plenty). Python 2 also has &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; type that can store text in various writing systems. A minimal unit of a &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; object is a Unicode codepoint (a Unicode character). Both &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects can be mixed and matched together, for example, concatenated using &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; operator.&lt;br /&gt;
&lt;br /&gt;
In Python 3 &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds Unicode characters, and for binary data a new &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; type was added. This type was also added to Python 2.7 to simplify porting to Python 3 but in Python 2.7 bytes is simply an alias for &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; types are incompatible, and an attempt to use both together will result in &amp;lt;code&amp;gt;TypeError&amp;lt;/code&amp;gt; exception. A &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; object can be converted to &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; using .decode() method, and a &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; is converted to &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; using .encode() method.&lt;br /&gt;
&lt;br /&gt;
=== Absolute Import ===&lt;br /&gt;
Python 3 uses so called “absolute import” and you can no longer import modules from inside a package using only a module name. You need to either to use either a fully qualified name or a “dotted” notation.&lt;br /&gt;
&lt;br /&gt;
Let’s assume that you have a foo package that contains bar and spam modules, and you need to import bar module from spam. In Python 2 you can do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But in Python 3 you need to use either&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import foo.bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from . import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating Point Division ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 applying division operator to int numbers produces int result. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 / 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Python 3 division operator always gives you a float result.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4/3&lt;br /&gt;
1.3333333333333333&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get an int result you need to use integer division operator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 // 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Print Function ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 print statement has been replaced with print() function. This is not very relevant to Kodi because using print in Python addons is discouraged and xbmc.log() function should be used to write messages to the Kodi log.&lt;br /&gt;
&lt;br /&gt;
=== Default Iterators ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 most function and methods that produce sequences return iterators instead of lists. For example, range() function and .items(), .keys(), .values() of dict type produce iterators instead of lists, and their Python 2 analogues — xrange() function and .iter* methods of dict type — have been removed.&lt;br /&gt;
&lt;br /&gt;
=== No long Integers ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 long integer type has been removed and int type can now hold a number of arbitrary length.&lt;br /&gt;
&lt;br /&gt;
Those are only some of the differences between Python 2 and 3. For a more complete list see [https://docs.python.org/3.6/whatsnew/3.0.html official Python documentation].&lt;br /&gt;
&lt;br /&gt;
== Some Useful Information ==&lt;br /&gt;
&lt;br /&gt;
As it was said above, Python 3 includes a number of incompatible changes, so to avoid situation when after upgrading Kodi for Python 3 support most Python addons will be broken developers should start to port their addons to be compatible with both Python 2 and 3. This is not a trivial task but fortunately there are a number of tools and recommendations to simplify this process. Here I’ll give you some advice and information about tools that will simplify creating portable code that runs on both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
=== Know Your Strings! ===&lt;br /&gt;
&lt;br /&gt;
This is the most problematic part of porting Python 2 code to Python 3 so I put it first. One of the most notable differences between Python 2 and 3 is clear separation between “textual” and “binary” strings, that is, between textual data and their binary representation. This difference is often difficult to understand, especially for novice developers (not only in Python), and the fact that in Python 2 you can mix together str (binary data) and unicode (textual data) adds to that difficulty.&lt;br /&gt;
&lt;br /&gt;
There are many explanations in the Internet, but here are the most basic things about strings that you need to know:&lt;br /&gt;
&lt;br /&gt;
“Textual” or Unicode strings (unicode in Python 2 and str in Python 3) hold text as a sequence of characters. A minimal unit in such strings is a Unicode character — an abstract entity that represent an alphabet symbol, a punctuation sign or other symbol included in the Unicode character table. Of course, such symbols have concrete internal binary representation (a computer is a binary machine after all), but this representation is not relevant to us. All you need to know is that “textual” strings contain text units without being tied to concrete binary representation.&lt;br /&gt;
&lt;br /&gt;
Unlike Unicode strings, binary strings (str in Python 2 and bytes in both Python 2 and 3) hold binary data, and a minimal unit of such strings is a byte or 8 bits. Historically, in Python 2 such strings are used for textual data encoded in ASCII or other 1-byte fixed-length encoding (e.g. Windows 1251 for Cyrillic alphabets). However, this approach has its limitation, that is why unicode type was introduced in Python 2, and in Python 3 it was renamed to str and made a default container for textual data.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 2 allows to mix and match Unicode and binary strings in the same context and this creates big problems when porting Python 2 code to Python 3. So in order to successfully port your code to Python 3 you need to carefully consider how textual data are processed in your addon. The following recommendations will help you avoid problems when writing Python 2/3 compatible code.&lt;br /&gt;
&lt;br /&gt;
=== Avoid using binary strings for text ===&lt;br /&gt;
&lt;br /&gt;
Store all your text as Unicode strings. This means that all binary strings received from external sources (textual files, websites, various APIs) need to be decoded using appropriate encoding (UTF-8 in most cases). If you need to use strings literals (although using hardcoded strings for user-facing text in Kodi is strongly discouraged), they need to be defined as unicode strings as well. You can use either&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
at the beginning of your modules to enable unicode strings by default as in Python 3 or u-strings, e.g. &amp;lt;code&amp;gt;u&#039;foo&#039;&amp;lt;/code&amp;gt; (Python 3 understands them too) — it doesn&#039;t really matter as long as you are doing it consistently.&lt;br /&gt;
&lt;br /&gt;
=== Know the libraries you are using ===&lt;br /&gt;
Working with Python Standard Library and third-party libraries (including Kodi Python API) you should know that types their functions and methods expect and what types they return. For example, in popular requests library Response.text property returns a Unicode string and Response.content returns a binary string.&lt;br /&gt;
&lt;br /&gt;
If a function/method/property returns a binary string, you need to decode it to a Unicode string using .decode() method. Don’t use unicode class constructor because unicode type does not exist in Python 3.&lt;br /&gt;
&lt;br /&gt;
If you are reading textual files from disk, it is better to use io.open() instead of built-in open(). io.open() can decode file contents to Unicode using specified encoding and works identically both in Python 2 and 3. Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import io&lt;br /&gt;
&lt;br /&gt;
with io.open(&#039;foo.txt&#039;, &#039;r&#039;, encoding=&#039;utf-8&#039;) as fo:&lt;br /&gt;
   text = fo.read()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Potential pitfalls ===&lt;br /&gt;
&lt;br /&gt;
When writing Python 2/3-compatible code or converting existing Python 2 codebase to compatible code you should pay attention to the following Python language constructions where TypeError exceptions may happen because of incompatible string types if you don’t get your strings in order:&lt;br /&gt;
&lt;br /&gt;
* String concatenations with + operator (&amp;lt;code&amp;gt;&#039;foo&#039; + &#039;bar&#039;&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String formatting — both “old style” (&amp;lt;code&amp;gt;&#039;foo %s&#039; % &#039;bar&#039;&amp;lt;/code&amp;gt;) and “new style” (&amp;lt;code&amp;gt;&#039;foo {}&#039;.format(&#039;bar&#039;)&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String joining (&amp;lt;code&amp;gt;&#039;, &#039;.join([&#039;foo&#039;, &#039;bar&#039;])&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
In all those cases always make sure that you work with Unicode strings only.&lt;br /&gt;
Another source of subtle bugs is functions and methods that accept and return binary strings (str type) in Python 2  but Unicode strings in Python 3 (again, str type but with different properties). You can use the following utility functions to “normalize” strings that are provided to such functions/methods and received from them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
__all__ = [&#039;PY2&#039;, &#039;py2_encode&#039;, &#039;py2_decode&#039;]&lt;br /&gt;
&lt;br /&gt;
PY2 = sys.version_info[0] == 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_encode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Encode Python 2 ``unicode`` to ``str``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.   &lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, unicode):&lt;br /&gt;
       s = s.encode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_decode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Decode Python 2 ``str`` to ``unicode``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, str):&lt;br /&gt;
       s = s.decode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Helper Libraries and Tools ==&lt;br /&gt;
&lt;br /&gt;
=== 2to3 ===&lt;br /&gt;
&lt;br /&gt;
[https://docs.python.org/2/library/2to3.html 2to3] script is created by Python developers to help converting existing Python 2 code to Python 3. On Windows it is included in Python distribution (Tools subfolder) but on other OSes you man need to install it separately. For example, on Ubuntu it is included in python-examples package. Note that this script is created for conversion from Python 2 to 3, not for writing portable code, so you need to treat its output with care.&lt;br /&gt;
&lt;br /&gt;
=== Modernize ===&lt;br /&gt;
&lt;br /&gt;
https://python-modernize.readthedocs.io/en/latest/ Modernize] script works on top of 2to3 and is supposed to help you to convert your existing Python 2 code to Python 2/3-compatible. However, in my experiments it did not work reliably even in simple cases so I cannot recommend it for usage.&lt;br /&gt;
&lt;br /&gt;
=== Six ===&lt;br /&gt;
&lt;br /&gt;
[https://pythonhosted.org/six/ Six] was the first library developed to simplify Python 2 to 3 migration. It provides a set of wrappers that hide differences between Python 2 and 3 behind its API. It is less intrusive than the following alternative because it does not monkey-patch built-in names, but in order to use Six library effectively you need to learn its API. Six can be used both for writing new Python 2/3-compatible addons and converting existing ones, but it requires good knowledge of Python 2/3 differences to pick necessary Six features that address specific differences.&lt;br /&gt;
&lt;br /&gt;
Six library is included in the Kodi addon repository as &#039;&#039;&#039;script.module.six addon&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Future ===&lt;br /&gt;
&lt;br /&gt;
[http://python-future.org/ Future] library, like Six, was created to simplify porting existing Python 2 code to 3. But it uses a different approach than Six. Future monkey-patches built-in Python objects to make Python 2 behave like Python 3. The advantage of such approach is that code written using Future is close to idiomatic Python 3 and requires little re-work if you decide to drop Python 2 support in the future. However, such approach may cause problems in some rare edge-cases.&lt;br /&gt;
&lt;br /&gt;
Future library also includes &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; command-line utility for converting existing Python 2 code to 2/3-compatible and in my experiments this utility showed good results.&lt;br /&gt;
Future library (without additional utilities) is included in the Kodi addon repository as script.module.future addon.&lt;br /&gt;
&lt;br /&gt;
=== PyCharm ===&lt;br /&gt;
&lt;br /&gt;
PyCharm, except for being a really good Python IDE, also provides code compatibility inspection that helps you write Python 2/3-portable code. Open &#039;&#039;&#039;Settings&#039;&#039;&#039; (Alt+F7) &amp;gt; &#039;&#039;&#039;Editor&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Inspections&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Python&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Code compatibility inspections&#039;&#039;&#039; and check Python version that you want to support.&lt;br /&gt;
&lt;br /&gt;
PyCharm Community Edition is free and provides all features you need for creating Python addons for Kodi.&lt;br /&gt;
&lt;br /&gt;
== Writing Portable Code ==&lt;br /&gt;
&lt;br /&gt;
Here I’ll give you some tips about how to write portable code:&lt;br /&gt;
&lt;br /&gt;
* Learn the differences between Python 2 and 3. You need to know at least the most important differences between the two major Python versions.&lt;br /&gt;
&lt;br /&gt;
* Use version control system — git or mercurial — to track changes in your code. If you are porting existing code, do it in a separate branch.&lt;br /&gt;
&lt;br /&gt;
* No matter if you are going to write a brand new addon or to port existing addon to Python 3, carefully choose your tools. It is totally possible to write portable code without any helper tools and libraries, but you need to know what you are doing. However, in most cases I’d recommend you to use Future library and its utilities. Carefully read Future documentation.&lt;br /&gt;
&lt;br /&gt;
* Put the following line at the beginning of all your modules:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will enable respective Python 3 features in your code. You don’t need to import print_function (another Python 3 feature) because in Kodi addons you should to use xbmc.log() to write messages to the Kodi log file.&lt;br /&gt;
&lt;br /&gt;
=== Writing New Addons ===&lt;br /&gt;
&lt;br /&gt;
Check the [http://python-future.org/quickstart.html#if-you-are-writing-code-from-scratch Quick Start Guide] section of Future library documentation. You can also use Six library, but, as it was said previously, you need to learn its API to pick the necessary features to address specific Python version differences, while Future allows to write your code in (almost) idiomatic Python 3.&lt;br /&gt;
&lt;br /&gt;
A brief procedure for writing new Python 2/3-compatible addons with Future library:&lt;br /&gt;
&lt;br /&gt;
# Create a new virtual environment with Python 3 interpreter and activate it.&lt;br /&gt;
# Install Future library: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Point your IDE (Integrated Development Environment) to that environment. For example, in PyCharm: &#039;&#039;&#039;File&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Setting&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project Interpreter&#039;&#039;&#039;.&lt;br /&gt;
# Put the following line at the beginning of your Python code:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
from future import standard_library&lt;br /&gt;
from future.builtins import *&lt;br /&gt;
standard_library.install_aliases()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Write your addon using Python 3 syntax and standard library names. However, you may still need to use wrappers from Future library for some specific cases. Read Future docs for more info.&lt;br /&gt;
&lt;br /&gt;
=== Porting Existing Addons ===&lt;br /&gt;
&lt;br /&gt;
A brief procedure for porting existing code to Python 3-compatible with Future library:&lt;br /&gt;
&lt;br /&gt;
# Install Future library into your working Python 2 virtual environment: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; utility to convert all your scripts and modules to portable code.&lt;br /&gt;
&lt;br /&gt;
Test your new or converted addon in Kodi with Python 2 interpreter and fix all found issues. After that test the addon in Kodi with Python 3 interpreter and again fix all found issues.&lt;br /&gt;
You can use [https://github.com/romanvm/kodi.web-pdb Web-PDB] debugger for troubleshooting issues in your code. It is compatible with both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* Python 2 and 3 differences: https://docs.python.org/3.6/whatsnew/3.0.html&lt;br /&gt;
* Future library documentation: http://python-future.org/&lt;br /&gt;
* Six library documentation: https://pythonhosted.org/six/&lt;br /&gt;
* Kodi test builds with Python 3 for Windows: http://mirrors.xbmc.org/test-builds/windows/win32/&lt;br /&gt;
* Kodi test builds with Python 3 for Linux Ubuntu: https://launchpad.net/~wsnipex/+archive/ubuntu/kodi-python3/+packages&lt;br /&gt;
* “Python 3 migration” section on the Kodi official forum: https://forum.kodi.tv/forumdisplay.php?fid=281&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132475</id>
		<title>General information about migration to Python 3</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132475"/>
		<updated>2018-01-19T09:55:03Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: /* Writing New Addons */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Python 3 was released 9 years ago and EOL for Python 2.7 is scheduled for 2020. Currently more and more Python project are switching to Python 3 or 2/3 compatible code. The issue of migrating Kodi’s built-in Python interpreter to Python 3.x was brought up on the Kodi forum several times. Now, thanks to a successful GSOC 2017 project, we have a working Python 3 interpreter for Kodi. That is why on Kodi DevCon 2017 Team Kodi decided that we will switch to Python 3 in the future Kodi release (v.19 preliminarily).&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 3.x versions are not backward-compatible with Python 2.x, so we decided to urge addon developers to start porting their addons to Python 3 by making the addons compatible with both Python 2 and 3 and submitting them to the official repo. This way, when Kodi with Python 3 is released, we won’t have a situation when we have no working addons.&lt;br /&gt;
&lt;br /&gt;
== The Process ==&lt;br /&gt;
&lt;br /&gt;
* Starting from Kodi 18 (Leia), only addons that are compatible with both Python 2 and 3 will be accepted to the official addon repository.&lt;br /&gt;
* We will provide Kodi builds with Python 3 so that addon developers can tests if their addons are really compatible with Python 3.&lt;br /&gt;
* A thread will be created on the Kodi forum so that addon devs can get help with their migration process.&lt;br /&gt;
&lt;br /&gt;
== Python 3 And 2 Differences ==&lt;br /&gt;
&lt;br /&gt;
Below is a brief overview of the main differences between Python 3 and 2.&lt;br /&gt;
&lt;br /&gt;
=== Unicode strings by default ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 built-in &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds the sequence of bytes so it can be used to store both binary data and textual data in ASCII or any of 8-bit fixed-length encodings (there were plenty). Python 2 also has &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; type that can store text in various writing systems. A minimal unit of a &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; object is a Unicode codepoint (a Unicode character). Both &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects can be mixed and matched together, for example, concatenated using &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; operator.&lt;br /&gt;
&lt;br /&gt;
In Python 3 &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds Unicode characters, and for binary data a new &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; type was added. This type was also added to Python 2.7 to simplify porting to Python 3 but in Python 2.7 bytes is simply an alias for &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; types are incompatible, and an attempt to use both together will result in &amp;lt;code&amp;gt;TypeError&amp;lt;/code&amp;gt; exception. A &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; object can be converted to &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; using .decode() method, and a &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; is converted to &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; using .encode() method.&lt;br /&gt;
&lt;br /&gt;
=== Absolute Import ===&lt;br /&gt;
Python 3 uses so called “absolute import” and you can no longer import modules from inside a package using only a module name. You need to either to use either a fully qualified name or a “dotted” notation.&lt;br /&gt;
&lt;br /&gt;
Let’s assume that you have a foo package that contains bar and spam modules, and you need to import bar module from spam. In Python 2 you can do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But in Python 3 you need to use either&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import foo.bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from . import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating Point Division ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 applying division operator to int numbers produces int result. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 / 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Python 3 division operator always gives you a float result.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4/3&lt;br /&gt;
1.3333333333333333&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get an int result you need to use integer division operator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 // 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Print Function ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 print statement has been replaced with print() function. This is not very relevant to Kodi because using print in Python addons is discouraged and xbmc.log() function should be used to write messages to the Kodi log.&lt;br /&gt;
&lt;br /&gt;
=== Default Iterators ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 most function and methods that produce sequences return iterators instead of lists. For example, range() function and .items(), .keys(), .values() of dict type produce iterators instead of lists, and their Python 2 analogues — xrange() function and .iter* methods of dict type — have been removed.&lt;br /&gt;
&lt;br /&gt;
=== No long Integers ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 long integer type has been removed and int type can now hold a number of arbitrary length.&lt;br /&gt;
&lt;br /&gt;
Those are only some of the differences between Python 2 and 3. For a more complete list see [https://docs.python.org/3.6/whatsnew/3.0.html official Python documentation].&lt;br /&gt;
&lt;br /&gt;
== Some Useful Information ==&lt;br /&gt;
&lt;br /&gt;
As it was said above, Python 3 includes a number of incompatible changes, so to avoid situation when after upgrading Kodi for Python 3 support most Python addons will be broken developers should start to port their addons to be compatible with both Python 2 and 3. This is not a trivial task but fortunately there are a number of tools and recommendations to simplify this process. Here I’ll give you some advice and information about tools that will simplify creating portable code that runs on both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
=== Know Your Strings! ===&lt;br /&gt;
&lt;br /&gt;
This is the most problematic part of porting Python 2 code to Python 3 so I put it first. One of the most notable differences between Python 2 and 3 is clear separation between “textual” and “binary” strings, that is, between textual data and their binary representation. This difference is often difficult to understand, especially for novice developers (not only in Python), and the fact that in Python 2 you can mix together str (binary data) and unicode (textual data) adds to that difficulty.&lt;br /&gt;
&lt;br /&gt;
There are many explanations in the Internet, but here are the most basic things about strings that you need to know:&lt;br /&gt;
&lt;br /&gt;
“Textual” or Unicode strings (unicode in Python 2 and str in Python 3) hold text as a sequence of characters. A minimal unit in such strings is a Unicode character — an abstract entity that represent an alphabet symbol, a punctuation sign or other symbol included in the Unicode character table. Of course, such symbols have concrete internal binary representation (a computer is a binary machine after all), but this representation is not relevant to us. All you need to know is that “textual” strings contain text units without being tied to concrete binary representation.&lt;br /&gt;
&lt;br /&gt;
Unlike Unicode strings, binary strings (str in Python 2 and bytes in both Python 2 and 3) hold binary data, and a minimal unit of such strings is a byte or 8 bits. Historically, in Python 2 such strings are used for textual data encoded in ASCII or other 1-byte fixed-length encoding (e.g. Windows 1251 for Cyrillic alphabets). However, this approach has its limitation, that is why unicode type was introduced in Python 2, and in Python 3 it was renamed to str and made a default container for textual data.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 2 allows to mix and match Unicode and binary strings in the same context and this creates big problems when porting Python 2 code to Python 3. So in order to successfully port your code to Python 3 you need to carefully consider how textual data are processed in your addon. The following recommendations will help you avoid problems when writing Python 2/3 compatible code.&lt;br /&gt;
&lt;br /&gt;
=== Avoid using binary strings for text ===&lt;br /&gt;
&lt;br /&gt;
Store all your text as Unicode strings. This means that all binary strings received from external sources (textual files, websites, various APIs) need to be decoded using appropriate encoding (UTF-8 in most cases). If you need to use strings literals (although using hardcoded strings for user-facing text in Kodi is strongly discouraged), they need to be defined as unicode strings as well. You can use either&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
at the beginning of your modules to enable unicode strings by default as in Python 3 or u-strings, e.g. &amp;lt;code&amp;gt;u&#039;foo&#039;&amp;lt;/code&amp;gt; (Python 3 understands them too) — it doesn&#039;t really matter as long as you are doing it consistently.&lt;br /&gt;
&lt;br /&gt;
=== Know the libraries you are using ===&lt;br /&gt;
Working with Python Standard Library and third-party libraries (including Kodi Python API) you should know that types their functions and methods expect and what types they return. For example, in popular requests library Response.text property returns a Unicode string and Response.content returns a binary string.&lt;br /&gt;
&lt;br /&gt;
If a function/method/property returns a binary string, you need to decode it to a Unicode string using .decode() method. Don’t use unicode class constructor because unicode type does not exist in Python 3.&lt;br /&gt;
&lt;br /&gt;
If you are reading textual files from disk, it is better to use io.open() instead of built-in open(). io.open() can decode file contents to Unicode using specified encoding and works identically both in Python 2 and 3. Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import io&lt;br /&gt;
&lt;br /&gt;
with io.open(&#039;foo.txt&#039;, &#039;r&#039;, encoding=&#039;utf-8&#039;) as fo:&lt;br /&gt;
   text = fo.read()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Potential pitfalls ===&lt;br /&gt;
&lt;br /&gt;
When writing Python 2/3-compatible code or converting existing Python 2 codebase to compatible code you should pay attention to the following Python language constructions where TypeError exceptions may happen because of incompatible string types if you don’t get your strings in order:&lt;br /&gt;
&lt;br /&gt;
* String concatenations with + operator (&amp;lt;code&amp;gt;&#039;foo&#039; + &#039;bar&#039;&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String formatting — both “old style” (&amp;lt;code&amp;gt;&#039;foo %s&#039; % &#039;bar&#039;&amp;lt;/code&amp;gt;) and “new style” (&amp;lt;code&amp;gt;&#039;foo {}&#039;.format(&#039;bar&#039;)&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String joining (&amp;lt;code&amp;gt;&#039;, &#039;.join([&#039;foo&#039;, &#039;bar&#039;])&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
In all those cases always make sure that you work with Unicode strings only.&lt;br /&gt;
Another source of subtle bugs is functions and methods that accept and return binary strings (str type) in Python 2  but Unicode strings in Python 3 (again, str type but with different properties). You can use the following utility functions to “normalize” strings that are provided to such functions/methods and received from them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
__all__ = [&#039;PY2&#039;, &#039;py2_encode&#039;, &#039;py2_decode&#039;]&lt;br /&gt;
&lt;br /&gt;
PY2 = sys.version_info[0] == 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_encode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Encode Python 2 ``unicode`` to ``str``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.   &lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, unicode):&lt;br /&gt;
       s = s.encode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_decode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Decode Python 2 ``str`` to ``unicode``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, str):&lt;br /&gt;
       s = s.decode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Helper Libraries and Tools ==&lt;br /&gt;
&lt;br /&gt;
=== 2to3 ===&lt;br /&gt;
&lt;br /&gt;
[https://docs.python.org/2/library/2to3.html 2to3] script is created by Python developers to help converting existing Python 2 code to Python 3. On Windows it is included in Python distribution (Tools subfolder) but on other OSes you man need to install it separately. For example, on Ubuntu it is included in python-examples package. Note that this script is created for conversion from Python 2 to 3, not for writing portable code, so you need to treat its output with care.&lt;br /&gt;
&lt;br /&gt;
=== Modernize ===&lt;br /&gt;
&lt;br /&gt;
https://python-modernize.readthedocs.io/en/latest/ Modernize] script works on top of 2to3 and is supposed to help you to convert your existing Python 2 code to Python 2/3-compatible. However, in my experiments it did not work reliably even in simple cases so I cannot recommend it for usage.&lt;br /&gt;
&lt;br /&gt;
=== Six ===&lt;br /&gt;
&lt;br /&gt;
[https://pythonhosted.org/six/ Six] was the first library developed to simplify Python 2 to 3 migration. It provides a set of wrappers that hide differences between Python 2 and 3 behind its API. It is less intrusive than the following alternative because it does not monkey-patch built-in names, but in order to use Six library effectively you need to learn its API. Six can be used both for writing new Python 2/3-compatible addons and converting existing ones, but it requires good knowledge of Python 2/3 differences to pick necessary Six features that address specific differences.&lt;br /&gt;
&lt;br /&gt;
Six library is included in the Kodi addon repository as &#039;&#039;&#039;script.module.six addon&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Future ===&lt;br /&gt;
&lt;br /&gt;
[http://python-future.org/ Future] library, like Six, was created to simplify porting existing Python 2 code to 3. But it uses a different approach than Six. Future monkey-patches built-in Python objects to make Python 2 behave like Python 3. The advantage of such approach is that code written using Future is close to idiomatic Python 3 and requires little re-work if you decide to drop Python 2 support in the future. However, such approach may cause problems in some rare edge-cases.&lt;br /&gt;
&lt;br /&gt;
Future library also includes &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; command-line utility for converting existing Python 2 code to 2/3-compatible and in my experiments this utility showed good results.&lt;br /&gt;
Future library (without additional utilities) is included in the Kodi addon repository as script.module.future addon.&lt;br /&gt;
&lt;br /&gt;
=== PyCharm ===&lt;br /&gt;
&lt;br /&gt;
PyCharm, except for being a really good Python IDE, also provides code compatibility inspection that helps you write Python 2/3-portable code. Open &#039;&#039;&#039;Settings&#039;&#039;&#039; (Alt+F7) &amp;gt; &#039;&#039;&#039;Editor&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Inspections&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Python&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Code compatibility inspections&#039;&#039;&#039; and check Python version that you want to support.&lt;br /&gt;
&lt;br /&gt;
PyCharm Community Edition is free and provides all features you need for creating Python addons for Kodi.&lt;br /&gt;
&lt;br /&gt;
== Writing Portable Code ==&lt;br /&gt;
&lt;br /&gt;
Here I’ll give you some tips about how to write portable code:&lt;br /&gt;
&lt;br /&gt;
* Learn the differences between Python 2 and 3. You need to know at least the most important differences between the two major Python versions.&lt;br /&gt;
&lt;br /&gt;
* Use version control system — git or mercurial — to track changes in your code. If you are porting existing code, do it in a separate branch.&lt;br /&gt;
&lt;br /&gt;
* No matter if you are going to write a brand new addon or to port existing addon to Python 3, carefully choose your tools. It is totally possible to write portable code without any helper tools and libraries, but you need to know what you are doing. However, in most cases I’d recommend you to use Future library and its utilities. Carefully read Future documentation.&lt;br /&gt;
&lt;br /&gt;
* Put the following line at the beginning of all your modules:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will enable respective Python 3 features in your code. You don’t need to import print_function (another Python 3 feature) because in Kodi addons you should to use xbmc.log() to write messages to the Kodi log file.&lt;br /&gt;
&lt;br /&gt;
=== Writing New Addons ===&lt;br /&gt;
&lt;br /&gt;
Check the [http://python-future.org/quickstart.html#if-you-are-writing-code-from-scratch Quick Start Guide] section of Future library documentation. You can also use Six library, but, as it was said previously, you need to learn its API to pick the necessary features to address specific Python version differences, while Future allows to write your code in (almost) idiomatic Python 3.&lt;br /&gt;
&lt;br /&gt;
A brief procedure for writing new Python 2/3-compatible addons with Future library:&lt;br /&gt;
&lt;br /&gt;
# Create a new virtual environment with Python 3 interpreter and activate it.&lt;br /&gt;
# Install Future library: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Point your IDE (Integrated Development Environment) to that environment. For example, in PyCharm: &#039;&#039;&#039;File&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Setting&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project Interpreter&#039;&#039;&#039;.&lt;br /&gt;
# Put the following line at the beginning of your Python code:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
from future.builtins import *&lt;br /&gt;
from future import standard_library&lt;br /&gt;
standard_library.install_aliases()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Write your addon using Python 3 syntax and standard library names. However, you may still need to use wrappers from Future library for some specific cases. Read Future docs for more info.&lt;br /&gt;
&lt;br /&gt;
=== Porting Existing Addons ===&lt;br /&gt;
&lt;br /&gt;
A brief procedure for porting existing code to Python 3-compatible with Future library:&lt;br /&gt;
&lt;br /&gt;
# Install Future library into your working Python 2 virtual environment: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; utility to convert all your scripts and modules to portable code.&lt;br /&gt;
&lt;br /&gt;
Test your new or converted addon in Kodi with Python 2 interpreter and fix all found issues. After that test the addon in Kodi with Python 3 interpreter and again fix all found issues.&lt;br /&gt;
You can use [https://github.com/romanvm/kodi.web-pdb Web-PDB] debugger for troubleshooting issues in your code. It is compatible with both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* Python 2 and 3 differences: https://docs.python.org/3.6/whatsnew/3.0.html&lt;br /&gt;
* Future library documentation: http://python-future.org/&lt;br /&gt;
* Six library documentation: https://pythonhosted.org/six/&lt;br /&gt;
* Kodi test builds with Python 3 for Windows: http://mirrors.xbmc.org/test-builds/windows/win32/&lt;br /&gt;
* Kodi test builds with Python 3 for Linux Ubuntu: https://launchpad.net/~wsnipex/+archive/ubuntu/kodi-python3/+packages&lt;br /&gt;
* “Python 3 migration” section on the Kodi official forum: https://forum.kodi.tv/forumdisplay.php?fid=281&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132301</id>
		<title>General information about migration to Python 3</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132301"/>
		<updated>2018-01-09T16:47:43Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: /* Writing New Addons */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Python 3 was released 9 years ago and EOL for Python 2.7 is scheduled for 2020. Currently more and more Python project are switching to Python 3 or 2/3 compatible code. The issue of migrating Kodi’s built-in Python interpreter to Python 3.x was brought up on the Kodi forum several times. Now, thanks to a successful GSOC 2017 project, we have a working Python 3 interpreter for Kodi. That is why on Kodi DevCon 2017 Team Kodi decided that we will switch to Python 3 in the future Kodi release (v.19 preliminarily).&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 3.x versions are not backward-compatible with Python 2.x, so we decided to urge addon developers to start porting their addons to Python 3 by making the addons compatible with both Python 2 and 3 and submitting them to the official repo. This way, when Kodi with Python 3 is released, we won’t have a situation when we have no working addons.&lt;br /&gt;
&lt;br /&gt;
== The Process ==&lt;br /&gt;
&lt;br /&gt;
* Starting from Kodi 18 (Leia), only addons that are compatible with both Python 2 and 3 will be accepted to the official addon repository.&lt;br /&gt;
* We will provide Kodi builds with Python 3 so that addon developers can tests if their addons are really compatible with Python 3.&lt;br /&gt;
* A thread will be created on the Kodi forum so that addon devs can get help with their migration process.&lt;br /&gt;
&lt;br /&gt;
== Python 3 And 2 Differences ==&lt;br /&gt;
&lt;br /&gt;
Below is a brief overview of the main differences between Python 3 and 2.&lt;br /&gt;
&lt;br /&gt;
=== Unicode strings by default ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 built-in &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds the sequence of bytes so it can be used to store both binary data and textual data in ASCII or any of 8-bit fixed-length encodings (there were plenty). Python 2 also has &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; type that can store text in various writing systems. A minimal unit of a &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; object is a Unicode codepoint (a Unicode character). Both &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects can be mixed and matched together, for example, concatenated using &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; operator.&lt;br /&gt;
&lt;br /&gt;
In Python 3 &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds Unicode characters, and for binary data a new &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; type was added. This type was also added to Python 2.7 to simplify porting to Python 3 but in Python 2.7 bytes is simply an alias for &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; types are incompatible, and an attempt to use both together will result in &amp;lt;code&amp;gt;TypeError&amp;lt;/code&amp;gt; exception. A &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; object can be converted to &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; using .decode() method, and a &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; is converted to &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; using .encode() method.&lt;br /&gt;
&lt;br /&gt;
=== Absolute Import ===&lt;br /&gt;
Python 3 uses so called “absolute import” and you can no longer import modules from inside a package using only a module name. You need to either to use either a fully qualified name or a “dotted” notation.&lt;br /&gt;
&lt;br /&gt;
Let’s assume that you have a foo package that contains bar and spam modules, and you need to import bar module from spam. In Python 2 you can do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But in Python 3 you need to use either&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import foo.bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from . import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating Point Division ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 applying division operator to int numbers produces int result. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 / 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Python 3 division operator always gives you a float result.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4/3&lt;br /&gt;
1.3333333333333333&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get an int result you need to use integer division operator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 // 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Print Function ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 print statement has been replaced with print() function. This is not very relevant to Kodi because using print in Python addons is discouraged and xbmc.log() function should be used to write messages to the Kodi log.&lt;br /&gt;
&lt;br /&gt;
=== Default Iterators ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 most function and methods that produce sequences return iterators instead of lists. For example, range() function and .items(), .keys(), .values() of dict type produce iterators instead of lists, and their Python 2 analogues — xrange() function and .iter* methods of dict type — have been removed.&lt;br /&gt;
&lt;br /&gt;
=== No long Integers ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 long integer type has been removed and int type can now hold a number of arbitrary length.&lt;br /&gt;
&lt;br /&gt;
Those are only some of the differences between Python 2 and 3. For a more complete list see [https://docs.python.org/3.6/whatsnew/3.0.html official Python documentation].&lt;br /&gt;
&lt;br /&gt;
== Some Useful Information ==&lt;br /&gt;
&lt;br /&gt;
As it was said above, Python 3 includes a number of incompatible changes, so to avoid situation when after upgrading Kodi for Python 3 support most Python addons will be broken developers should start to port their addons to be compatible with both Python 2 and 3. This is not a trivial task but fortunately there are a number of tools and recommendations to simplify this process. Here I’ll give you some advice and information about tools that will simplify creating portable code that runs on both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
=== Know Your Strings! ===&lt;br /&gt;
&lt;br /&gt;
This is the most problematic part of porting Python 2 code to Python 3 so I put it first. One of the most notable differences between Python 2 and 3 is clear separation between “textual” and “binary” strings, that is, between textual data and their binary representation. This difference is often difficult to understand, especially for novice developers (not only in Python), and the fact that in Python 2 you can mix together str (binary data) and unicode (textual data) adds to that difficulty.&lt;br /&gt;
&lt;br /&gt;
There are many explanations in the Internet, but here are the most basic things about strings that you need to know:&lt;br /&gt;
&lt;br /&gt;
“Textual” or Unicode strings (unicode in Python 2 and str in Python 3) hold text as a sequence of characters. A minimal unit in such strings is a Unicode character — an abstract entity that represent an alphabet symbol, a punctuation sign or other symbol included in the Unicode character table. Of course, such symbols have concrete internal binary representation (a computer is a binary machine after all), but this representation is not relevant to us. All you need to know is that “textual” strings contain text units without being tied to concrete binary representation.&lt;br /&gt;
&lt;br /&gt;
Unlike Unicode strings, binary strings (str in Python 2 and bytes in both Python 2 and 3) hold binary data, and a minimal unit of such strings is a byte or 8 bits. Historically, in Python 2 such strings are used for textual data encoded in ASCII or other 1-byte fixed-length encoding (e.g. Windows 1251 for Cyrillic alphabets). However, this approach has its limitation, that is why unicode type was introduced in Python 2, and in Python 3 it was renamed to str and made a default container for textual data.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 2 allows to mix and match Unicode and binary strings in the same context and this creates big problems when porting Python 2 code to Python 3. So in order to successfully port your code to Python 3 you need to carefully consider how textual data are processed in your addon. The following recommendations will help you avoid problems when writing Python 2/3 compatible code.&lt;br /&gt;
&lt;br /&gt;
=== Avoid using binary strings for text ===&lt;br /&gt;
&lt;br /&gt;
Store all your text as Unicode strings. This means that all binary strings received from external sources (textual files, websites, various APIs) need to be decoded using appropriate encoding (UTF-8 in most cases). If you need to use strings literals (although using hardcoded strings for user-facing text in Kodi is strongly discouraged), they need to be defined as unicode strings as well. You can use either&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
at the beginning of your modules to enable unicode strings by default as in Python 3 or u-strings, e.g. &amp;lt;code&amp;gt;u&#039;foo&#039;&amp;lt;/code&amp;gt; (Python 3 understands them too) — it doesn&#039;t really matter as long as you are doing it consistently.&lt;br /&gt;
&lt;br /&gt;
=== Know the libraries you are using ===&lt;br /&gt;
Working with Python Standard Library and third-party libraries (including Kodi Python API) you should know that types their functions and methods expect and what types they return. For example, in popular requests library Response.text property returns a Unicode string and Response.content returns a binary string.&lt;br /&gt;
&lt;br /&gt;
If a function/method/property returns a binary string, you need to decode it to a Unicode string using .decode() method. Don’t use unicode class constructor because unicode type does not exist in Python 3.&lt;br /&gt;
&lt;br /&gt;
If you are reading textual files from disk, it is better to use io.open() instead of built-in open(). io.open() can decode file contents to Unicode using specified encoding and works identically both in Python 2 and 3. Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import io&lt;br /&gt;
&lt;br /&gt;
with io.open(&#039;foo.txt&#039;, &#039;r&#039;, encoding=&#039;utf-8&#039;) as fo:&lt;br /&gt;
   text = fo.read()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Potential pitfalls ===&lt;br /&gt;
&lt;br /&gt;
When writing Python 2/3-compatible code or converting existing Python 2 codebase to compatible code you should pay attention to the following Python language constructions where TypeError exceptions may happen because of incompatible string types if you don’t get your strings in order:&lt;br /&gt;
&lt;br /&gt;
* String concatenations with + operator (&amp;lt;code&amp;gt;&#039;foo&#039; + &#039;bar&#039;&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String formatting — both “old style” (&amp;lt;code&amp;gt;&#039;foo %s&#039; % &#039;bar&#039;&amp;lt;/code&amp;gt;) and “new style” (&amp;lt;code&amp;gt;&#039;foo {}&#039;.format(&#039;bar&#039;)&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String joining (&amp;lt;code&amp;gt;&#039;, &#039;.join([&#039;foo&#039;, &#039;bar&#039;])&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
In all those cases always make sure that you work with Unicode strings only.&lt;br /&gt;
Another source of subtle bugs is functions and methods that accept and return binary strings (str type) in Python 2  but Unicode strings in Python 3 (again, str type but with different properties). You can use the following utility functions to “normalize” strings that are provided to such functions/methods and received from them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
__all__ = [&#039;PY2&#039;, &#039;py2_encode&#039;, &#039;py2_decode&#039;]&lt;br /&gt;
&lt;br /&gt;
PY2 = sys.version_info[0] == 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_encode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Encode Python 2 ``unicode`` to ``str``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.   &lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, unicode):&lt;br /&gt;
       s = s.encode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_decode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Decode Python 2 ``str`` to ``unicode``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, str):&lt;br /&gt;
       s = s.decode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Helper Libraries and Tools ==&lt;br /&gt;
&lt;br /&gt;
=== 2to3 ===&lt;br /&gt;
&lt;br /&gt;
[https://docs.python.org/2/library/2to3.html 2to3] script is created by Python developers to help converting existing Python 2 code to Python 3. On Windows it is included in Python distribution (Tools subfolder) but on other OSes you man need to install it separately. For example, on Ubuntu it is included in python-examples package. Note that this script is created for conversion from Python 2 to 3, not for writing portable code, so you need to treat its output with care.&lt;br /&gt;
&lt;br /&gt;
=== Modernize ===&lt;br /&gt;
&lt;br /&gt;
https://python-modernize.readthedocs.io/en/latest/ Modernize] script works on top of 2to3 and is supposed to help you to convert your existing Python 2 code to Python 2/3-compatible. However, in my experiments it did not work reliably even in simple cases so I cannot recommend it for usage.&lt;br /&gt;
&lt;br /&gt;
=== Six ===&lt;br /&gt;
&lt;br /&gt;
[https://pythonhosted.org/six/ Six] was the first library developed to simplify Python 2 to 3 migration. It provides a set of wrappers that hide differences between Python 2 and 3 behind its API. It is less intrusive than the following alternative because it does not monkey-patch built-in names, but in order to use Six library effectively you need to learn its API. Six can be used both for writing new Python 2/3-compatible addons and converting existing ones, but it requires good knowledge of Python 2/3 differences to pick necessary Six features that address specific differences.&lt;br /&gt;
&lt;br /&gt;
Six library is included in the Kodi addon repository as &#039;&#039;&#039;script.module.six addon&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Future ===&lt;br /&gt;
&lt;br /&gt;
[http://python-future.org/ Future] library, like Six, was created to simplify porting existing Python 2 code to 3. But it uses a different approach than Six. Future monkey-patches built-in Python objects to make Python 2 behave like Python 3. The advantage of such approach is that code written using Future is close to idiomatic Python 3 and requires little re-work if you decide to drop Python 2 support in the future. However, such approach may cause problems in some rare edge-cases.&lt;br /&gt;
&lt;br /&gt;
Future library also includes &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; command-line utility for converting existing Python 2 code to 2/3-compatible and in my experiments this utility showed good results.&lt;br /&gt;
Future library (without additional utilities) is included in the Kodi addon repository as script.module.future addon.&lt;br /&gt;
&lt;br /&gt;
=== PyCharm ===&lt;br /&gt;
&lt;br /&gt;
PyCharm, except for being a really good Python IDE, also provides code compatibility inspection that helps you write Python 2/3-portable code. Open &#039;&#039;&#039;Settings&#039;&#039;&#039; (Alt+F7) &amp;gt; &#039;&#039;&#039;Editor&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Inspections&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Python&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Code compatibility inspections&#039;&#039;&#039; and check Python version that you want to support.&lt;br /&gt;
&lt;br /&gt;
PyCharm Community Edition is free and provides all features you need for creating Python addons for Kodi.&lt;br /&gt;
&lt;br /&gt;
== Writing Portable Code ==&lt;br /&gt;
&lt;br /&gt;
Here I’ll give you some tips about how to write portable code:&lt;br /&gt;
&lt;br /&gt;
* Learn the differences between Python 2 and 3. You need to know at least the most important differences between the two major Python versions.&lt;br /&gt;
&lt;br /&gt;
* Use version control system — git or mercurial — to track changes in your code. If you are porting existing code, do it in a separate branch.&lt;br /&gt;
&lt;br /&gt;
* No matter if you are going to write a brand new addon or to port existing addon to Python 3, carefully choose your tools. It is totally possible to write portable code without any helper tools and libraries, but you need to know what you are doing. However, in most cases I’d recommend you to use Future library and its utilities. Carefully read Future documentation.&lt;br /&gt;
&lt;br /&gt;
* Put the following line at the beginning of all your modules:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will enable respective Python 3 features in your code. You don’t need to import print_function (another Python 3 feature) because in Kodi addons you should to use xbmc.log() to write messages to the Kodi log file.&lt;br /&gt;
&lt;br /&gt;
=== Writing New Addons ===&lt;br /&gt;
&lt;br /&gt;
Check the [http://python-future.org/quickstart.html#if-you-are-writing-code-from-scratch Quick Start Guide] section of Future library documentation. You can also use Six library, but, as it was said previously, you need to learn its API to pick the necessary features to address specific Python version differences, while Future allows to write your code in (almost) idiomatic Python 3.&lt;br /&gt;
&lt;br /&gt;
A brief procedure for writing new Python 2/3-compatible addons with Future library:&lt;br /&gt;
&lt;br /&gt;
# Create a new virtual environment with Python 3 interpreter and activate it.&lt;br /&gt;
# Install Future library: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Point your IDE (Integrated Development Environment) to that environment. For example, in PyCharm: &#039;&#039;&#039;File&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Setting&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project Interpreter&#039;&#039;&#039;.&lt;br /&gt;
# Put the following line at the beginning of your Python code:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
from builtins import *&lt;br /&gt;
from future import standard_library&lt;br /&gt;
standard_library.install_aliases()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Write your addon using Python 3 syntax and standard library names. However, you may still need to use wrappers from Future library for some specific cases. Read Future docs for more info.&lt;br /&gt;
&lt;br /&gt;
=== Porting Existing Addons ===&lt;br /&gt;
&lt;br /&gt;
A brief procedure for porting existing code to Python 3-compatible with Future library:&lt;br /&gt;
&lt;br /&gt;
# Install Future library into your working Python 2 virtual environment: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; utility to convert all your scripts and modules to portable code.&lt;br /&gt;
&lt;br /&gt;
Test your new or converted addon in Kodi with Python 2 interpreter and fix all found issues. After that test the addon in Kodi with Python 3 interpreter and again fix all found issues.&lt;br /&gt;
You can use [https://github.com/romanvm/kodi.web-pdb Web-PDB] debugger for troubleshooting issues in your code. It is compatible with both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* Python 2 and 3 differences: https://docs.python.org/3.6/whatsnew/3.0.html&lt;br /&gt;
* Future library documentation: http://python-future.org/&lt;br /&gt;
* Six library documentation: https://pythonhosted.org/six/&lt;br /&gt;
* Kodi test builds with Python 3 for Windows: http://mirrors.xbmc.org/test-builds/windows/win32/&lt;br /&gt;
* Kodi test builds with Python 3 for Linux Ubuntu: https://launchpad.net/~wsnipex/+archive/ubuntu/kodi-python3/+packages&lt;br /&gt;
* “Python 3 migration” section on the Kodi official forum: https://forum.kodi.tv/forumdisplay.php?fid=281&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=HOW-TO:Debug_Python_Scripts_with_Web-PDB&amp;diff=132228</id>
		<title>HOW-TO:Debug Python Scripts with Web-PDB</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=HOW-TO:Debug_Python_Scripts_with_Web-PDB&amp;diff=132228"/>
		<updated>2018-01-06T09:27:50Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://github.com/romanvm/kodi.web-pdb Web-PDB] is a remote web-interface to Python&#039;s built-in [https://docs.python.org/2/library/pdb.html PDB] debugger with additional convenience features. It is not tied to any IDE or other software, all you need is a common web-browser, e.g. Chrome or Firefox.&lt;br /&gt;
[[File:web-pdb.png]]&lt;br /&gt;
&lt;br /&gt;
Web-PDB for Kodi is available as an addon in the official Kodi addons repo.&lt;br /&gt;
&lt;br /&gt;
== How To Use Web-PDB for Kodi ==&lt;br /&gt;
&lt;br /&gt;
1. Install Web-PDB addon: &#039;&#039;&#039;Kodi Add-on repository &amp;gt; Program add-ons &amp;gt; Web-PDB&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
2. Add &amp;lt;code&amp;gt;script.module.web-pdb&amp;lt;/code&amp;gt; to [[addon.xml]] as a dependency:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;requires&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
   &amp;lt;import addon=&amp;quot;script.module.web-pdb&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;requires&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. Restart Kodi so that it re-reads addon dependencies.&lt;br /&gt;
&lt;br /&gt;
4. Insert the following line into your addon code at the point where you want to start debugging:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
import web_pdb; web_pdb.set_trace()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;set_trace()&amp;lt;/code&amp;gt; call will suspend your addon and open a web-UI at the default port 5555 (port value can be changed). At the same time a notification will be displayed in Kodi, indicating that a debug session is active. The notification also shows web-UI host/port.&lt;br /&gt;
&lt;br /&gt;
5. Enter in your the address bar of your browser: &amp;lt;code&amp;gt;http://&amp;lt;your Kodi machine hostname or IP&amp;gt;:5555&amp;lt;/code&amp;gt;, for example &amp;lt;code&amp;gt;http://monty-python:5555&amp;lt;/code&amp;gt;. Use &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt; as a hostname if you are connecting from the same machine that runs Kodi. If everything is OK, you should see the Web-PDB UI. Now you can use all PDB commands and features. Additional &#039;&#039;&#039;Current file&#039;&#039;&#039;, &#039;&#039;&#039;Globals&#039;&#039;&#039; and &#039;&#039;&#039;Locals&#039;&#039;&#039; information boxes help you better track your program runtime state.&lt;br /&gt;
&lt;br /&gt;
== More Information ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/romanvm/kodi.web-pdb Web-PDB for Kodi on GitHub].&lt;br /&gt;
* [https://docs.python.org/2/library/pdb.html PDB debugger documentation].&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=File:Web-pdb.png&amp;diff=132227</id>
		<title>File:Web-pdb.png</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=File:Web-pdb.png&amp;diff=132227"/>
		<updated>2018-01-06T09:22:39Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: Web-PDB debugger screenshot&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Web-PDB debugger screenshot&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132213</id>
		<title>General information about migration to Python 3</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132213"/>
		<updated>2018-01-04T11:28:24Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: /* Unicode strings by default */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Python 3 was released 9 years ago and EOL for Python 2.7 is scheduled for 2020. Currently more and more Python project are switching to Python 3 or 2/3 compatible code. The issue of migrating Kodi’s built-in Python interpreter to Python 3.x was brought up on the Kodi forum several times. Now, thanks to a successful GSOC 2017 project, we have a working Python 3 interpreter for Kodi. That is why on Kodi DevCon 2017 Team Kodi decided that we will switch to Python 3 in the future Kodi release (v.19 preliminarily).&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 3.x versions are not backward-compatible with Python 2.x, so we decided to urge addon developers to start porting their addons to Python 3 by making the addons compatible with both Python 2 and 3 and submitting them to the official repo. This way, when Kodi with Python 3 is released, we won’t have a situation when we have no working addons.&lt;br /&gt;
&lt;br /&gt;
== The Process ==&lt;br /&gt;
&lt;br /&gt;
* Starting from Kodi 18 (Leia), only addons that are compatible with both Python 2 and 3 will be accepted to the official addon repository.&lt;br /&gt;
* We will provide Kodi builds with Python 3 so that addon developers can tests if their addons are really compatible with Python 3.&lt;br /&gt;
* A thread will be created on the Kodi forum so that addon devs can get help with their migration process.&lt;br /&gt;
&lt;br /&gt;
== Python 3 And 2 Differences ==&lt;br /&gt;
&lt;br /&gt;
Below is a brief overview of the main differences between Python 3 and 2.&lt;br /&gt;
&lt;br /&gt;
=== Unicode strings by default ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 built-in &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds the sequence of bytes so it can be used to store both binary data and textual data in ASCII or any of 8-bit fixed-length encodings (there were plenty). Python 2 also has &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; type that can store text in various writing systems. A minimal unit of a &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; object is a Unicode codepoint (a Unicode character). Both &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects can be mixed and matched together, for example, concatenated using &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; operator.&lt;br /&gt;
&lt;br /&gt;
In Python 3 &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds Unicode characters, and for binary data a new &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; type was added. This type was also added to Python 2.7 to simplify porting to Python 3 but in Python 2.7 bytes is simply an alias for &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; types are incompatible, and an attempt to use both together will result in &amp;lt;code&amp;gt;TypeError&amp;lt;/code&amp;gt; exception. A &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; object can be converted to &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; using .decode() method, and a &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; is converted to &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; using .encode() method.&lt;br /&gt;
&lt;br /&gt;
=== Absolute Import ===&lt;br /&gt;
Python 3 uses so called “absolute import” and you can no longer import modules from inside a package using only a module name. You need to either to use either a fully qualified name or a “dotted” notation.&lt;br /&gt;
&lt;br /&gt;
Let’s assume that you have a foo package that contains bar and spam modules, and you need to import bar module from spam. In Python 2 you can do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But in Python 3 you need to use either&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import foo.bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from . import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating Point Division ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 applying division operator to int numbers produces int result. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 / 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Python 3 division operator always gives you a float result.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4/3&lt;br /&gt;
1.3333333333333333&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get an int result you need to use integer division operator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 // 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Print Function ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 print statement has been replaced with print() function. This is not very relevant to Kodi because using print in Python addons is discouraged and xbmc.log() function should be used to write messages to the Kodi log.&lt;br /&gt;
&lt;br /&gt;
=== Default Iterators ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 most function and methods that produce sequences return iterators instead of lists. For example, range() function and .items(), .keys(), .values() of dict type produce iterators instead of lists, and their Python 2 analogues — xrange() function and .iter* methods of dict type — have been removed.&lt;br /&gt;
&lt;br /&gt;
=== No long Integers ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 long integer type has been removed and int type can now hold a number of arbitrary length.&lt;br /&gt;
&lt;br /&gt;
Those are only some of the differences between Python 2 and 3. For a more complete list see [https://docs.python.org/3.6/whatsnew/3.0.html official Python documentation].&lt;br /&gt;
&lt;br /&gt;
== Some Useful Information ==&lt;br /&gt;
&lt;br /&gt;
As it was said above, Python 3 includes a number of incompatible changes, so to avoid situation when after upgrading Kodi for Python 3 support most Python addons will be broken developers should start to port their addons to be compatible with both Python 2 and 3. This is not a trivial task but fortunately there are a number of tools and recommendations to simplify this process. Here I’ll give you some advice and information about tools that will simplify creating portable code that runs on both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
=== Know Your Strings! ===&lt;br /&gt;
&lt;br /&gt;
This is the most problematic part of porting Python 2 code to Python 3 so I put it first. One of the most notable differences between Python 2 and 3 is clear separation between “textual” and “binary” strings, that is, between textual data and their binary representation. This difference is often difficult to understand, especially for novice developers (not only in Python), and the fact that in Python 2 you can mix together str (binary data) and unicode (textual data) adds to that difficulty.&lt;br /&gt;
&lt;br /&gt;
There are many explanations in the Internet, but here are the most basic things about strings that you need to know:&lt;br /&gt;
&lt;br /&gt;
“Textual” or Unicode strings (unicode in Python 2 and str in Python 3) hold text as a sequence of characters. A minimal unit in such strings is a Unicode character — an abstract entity that represent an alphabet symbol, a punctuation sign or other symbol included in the Unicode character table. Of course, such symbols have concrete internal binary representation (a computer is a binary machine after all), but this representation is not relevant to us. All you need to know is that “textual” strings contain text units without being tied to concrete binary representation.&lt;br /&gt;
&lt;br /&gt;
Unlike Unicode strings, binary strings (str in Python 2 and bytes in both Python 2 and 3) hold binary data, and a minimal unit of such strings is a byte or 8 bits. Historically, in Python 2 such strings are used for textual data encoded in ASCII or other 1-byte fixed-length encoding (e.g. Windows 1251 for Cyrillic alphabets). However, this approach has its limitation, that is why unicode type was introduced in Python 2, and in Python 3 it was renamed to str and made a default container for textual data.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 2 allows to mix and match Unicode and binary strings in the same context and this creates big problems when porting Python 2 code to Python 3. So in order to successfully port your code to Python 3 you need to carefully consider how textual data are processed in your addon. The following recommendations will help you avoid problems when writing Python 2/3 compatible code.&lt;br /&gt;
&lt;br /&gt;
=== Avoid using binary strings for text ===&lt;br /&gt;
&lt;br /&gt;
Store all your text as Unicode strings. This means that all binary strings received from external sources (textual files, websites, various APIs) need to be decoded using appropriate encoding (UTF-8 in most cases). If you need to use strings literals (although using hardcoded strings for user-facing text in Kodi is strongly discouraged), they need to be defined as unicode strings as well. You can use either&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
at the beginning of your modules to enable unicode strings by default as in Python 3 or u-strings, e.g. &amp;lt;code&amp;gt;u&#039;foo&#039;&amp;lt;/code&amp;gt; (Python 3 understands them too) — it doesn&#039;t really matter as long as you are doing it consistently.&lt;br /&gt;
&lt;br /&gt;
=== Know the libraries you are using ===&lt;br /&gt;
Working with Python Standard Library and third-party libraries (including Kodi Python API) you should know that types their functions and methods expect and what types they return. For example, in popular requests library Response.text property returns a Unicode string and Response.content returns a binary string.&lt;br /&gt;
&lt;br /&gt;
If a function/method/property returns a binary string, you need to decode it to a Unicode string using .decode() method. Don’t use unicode class constructor because unicode type does not exist in Python 3.&lt;br /&gt;
&lt;br /&gt;
If you are reading textual files from disk, it is better to use io.open() instead of built-in open(). io.open() can decode file contents to Unicode using specified encoding and works identically both in Python 2 and 3. Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import io&lt;br /&gt;
&lt;br /&gt;
with io.open(&#039;foo.txt&#039;, &#039;r&#039;, encoding=&#039;utf-8&#039;) as fo:&lt;br /&gt;
   text = fo.read()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Potential pitfalls ===&lt;br /&gt;
&lt;br /&gt;
When writing Python 2/3-compatible code or converting existing Python 2 codebase to compatible code you should pay attention to the following Python language constructions where TypeError exceptions may happen because of incompatible string types if you don’t get your strings in order:&lt;br /&gt;
&lt;br /&gt;
* String concatenations with + operator (&amp;lt;code&amp;gt;&#039;foo&#039; + &#039;bar&#039;&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String formatting — both “old style” (&amp;lt;code&amp;gt;&#039;foo %s&#039; % &#039;bar&#039;&amp;lt;/code&amp;gt;) and “new style” (&amp;lt;code&amp;gt;&#039;foo {}&#039;.format(&#039;bar&#039;)&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String joining (&amp;lt;code&amp;gt;&#039;, &#039;.join([&#039;foo&#039;, &#039;bar&#039;])&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
In all those cases always make sure that you work with Unicode strings only.&lt;br /&gt;
Another source of subtle bugs is functions and methods that accept and return binary strings (str type) in Python 2  but Unicode strings in Python 3 (again, str type but with different properties). You can use the following utility functions to “normalize” strings that are provided to such functions/methods and received from them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
__all__ = [&#039;PY2&#039;, &#039;py2_encode&#039;, &#039;py2_decode&#039;]&lt;br /&gt;
&lt;br /&gt;
PY2 = sys.version_info[0] == 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_encode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Encode Python 2 ``unicode`` to ``str``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.   &lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, unicode):&lt;br /&gt;
       s = s.encode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_decode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Decode Python 2 ``str`` to ``unicode``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, str):&lt;br /&gt;
       s = s.decode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Helper Libraries and Tools ==&lt;br /&gt;
&lt;br /&gt;
=== 2to3 ===&lt;br /&gt;
&lt;br /&gt;
[https://docs.python.org/2/library/2to3.html 2to3] script is created by Python developers to help converting existing Python 2 code to Python 3. On Windows it is included in Python distribution (Tools subfolder) but on other OSes you man need to install it separately. For example, on Ubuntu it is included in python-examples package. Note that this script is created for conversion from Python 2 to 3, not for writing portable code, so you need to treat its output with care.&lt;br /&gt;
&lt;br /&gt;
=== Modernize ===&lt;br /&gt;
&lt;br /&gt;
https://python-modernize.readthedocs.io/en/latest/ Modernize] script works on top of 2to3 and is supposed to help you to convert your existing Python 2 code to Python 2/3-compatible. However, in my experiments it did not work reliably even in simple cases so I cannot recommend it for usage.&lt;br /&gt;
&lt;br /&gt;
=== Six ===&lt;br /&gt;
&lt;br /&gt;
[https://pythonhosted.org/six/ Six] was the first library developed to simplify Python 2 to 3 migration. It provides a set of wrappers that hide differences between Python 2 and 3 behind its API. It is less intrusive than the following alternative because it does not monkey-patch built-in names, but in order to use Six library effectively you need to learn its API. Six can be used both for writing new Python 2/3-compatible addons and converting existing ones, but it requires good knowledge of Python 2/3 differences to pick necessary Six features that address specific differences.&lt;br /&gt;
&lt;br /&gt;
Six library is included in the Kodi addon repository as &#039;&#039;&#039;script.module.six addon&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Future ===&lt;br /&gt;
&lt;br /&gt;
[http://python-future.org/ Future] library, like Six, was created to simplify porting existing Python 2 code to 3. But it uses a different approach than Six. Future monkey-patches built-in Python objects to make Python 2 behave like Python 3. The advantage of such approach is that code written using Future is close to idiomatic Python 3 and requires little re-work if you decide to drop Python 2 support in the future. However, such approach may cause problems in some rare edge-cases.&lt;br /&gt;
&lt;br /&gt;
Future library also includes &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; command-line utility for converting existing Python 2 code to 2/3-compatible and in my experiments this utility showed good results.&lt;br /&gt;
Future library (without additional utilities) is included in the Kodi addon repository as script.module.future addon.&lt;br /&gt;
&lt;br /&gt;
=== PyCharm ===&lt;br /&gt;
&lt;br /&gt;
PyCharm, except for being a really good Python IDE, also provides code compatibility inspection that helps you write Python 2/3-portable code. Open &#039;&#039;&#039;Settings&#039;&#039;&#039; (Alt+F7) &amp;gt; &#039;&#039;&#039;Editor&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Inspections&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Python&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Code compatibility inspections&#039;&#039;&#039; and check Python version that you want to support.&lt;br /&gt;
&lt;br /&gt;
PyCharm Community Edition is free and provides all features you need for creating Python addons for Kodi.&lt;br /&gt;
&lt;br /&gt;
== Writing Portable Code ==&lt;br /&gt;
&lt;br /&gt;
Here I’ll give you some tips about how to write portable code:&lt;br /&gt;
&lt;br /&gt;
* Learn the differences between Python 2 and 3. You need to know at least the most important differences between the two major Python versions.&lt;br /&gt;
&lt;br /&gt;
* Use version control system — git or mercurial — to track changes in your code. If you are porting existing code, do it in a separate branch.&lt;br /&gt;
&lt;br /&gt;
* No matter if you are going to write a brand new addon or to port existing addon to Python 3, carefully choose your tools. It is totally possible to write portable code without any helper tools and libraries, but you need to know what you are doing. However, in most cases I’d recommend you to use Future library and its utilities. Carefully read Future documentation.&lt;br /&gt;
&lt;br /&gt;
* Put the following line at the beginning of all your modules:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will enable respective Python 3 features in your code. You don’t need to import print_function (another Python 3 feature) because in Kodi addons you should to use xbmc.log() to write messages to the Kodi log file.&lt;br /&gt;
&lt;br /&gt;
=== Writing New Addons ===&lt;br /&gt;
&lt;br /&gt;
Check the [http://python-future.org/quickstart.html#if-you-are-writing-code-from-scratch Quick Start Guide] section of Future library documentation. You can also use Six library, but, as it was said previously, you need to learn its API to pick the necessary features to address specific Python version differences, while Future allows to write your code in (almost) idiomatic Python 3.&lt;br /&gt;
&lt;br /&gt;
A brief procedure for writing new Python 2/3-compatible addons with Future library:&lt;br /&gt;
&lt;br /&gt;
# Create a new virtual environment with Python 3 interpreter and activate it.&lt;br /&gt;
# Install Future library: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Point your IDE (Integrated Development Environment) to that environment. For example, in PyCharm: &#039;&#039;&#039;File&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Setting&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project Interpreter&#039;&#039;&#039;.&lt;br /&gt;
# Put the following line at the beginning of your Python code:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
from builtins import *&lt;br /&gt;
from future import standard_library&lt;br /&gt;
standard_library.install_aliases()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Write your addon using Python 3 syntax and standard library names.&lt;br /&gt;
&lt;br /&gt;
=== Porting Existing Addons ===&lt;br /&gt;
&lt;br /&gt;
A brief procedure for porting existing code to Python 3-compatible with Future library:&lt;br /&gt;
&lt;br /&gt;
# Install Future library into your working Python 2 virtual environment: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; utility to convert all your scripts and modules to portable code.&lt;br /&gt;
&lt;br /&gt;
Test your new or converted addon in Kodi with Python 2 interpreter and fix all found issues. After that test the addon in Kodi with Python 3 interpreter and again fix all found issues.&lt;br /&gt;
You can use [https://github.com/romanvm/kodi.web-pdb Web-PDB] debugger for troubleshooting issues in your code. It is compatible with both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* Python 2 and 3 differences: https://docs.python.org/3.6/whatsnew/3.0.html&lt;br /&gt;
* Future library documentation: http://python-future.org/&lt;br /&gt;
* Six library documentation: https://pythonhosted.org/six/&lt;br /&gt;
* Kodi test builds with Python 3 for Windows: http://mirrors.xbmc.org/test-builds/windows/win32/&lt;br /&gt;
* Kodi test builds with Python 3 for Linux Ubuntu: https://launchpad.net/~wsnipex/+archive/ubuntu/kodi-python3/+packages&lt;br /&gt;
* “Python 3 migration” section on the Kodi official forum: https://forum.kodi.tv/forumdisplay.php?fid=281&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132212</id>
		<title>General information about migration to Python 3</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132212"/>
		<updated>2018-01-04T11:27:12Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: /* Unicode strings by default */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Python 3 was released 9 years ago and EOL for Python 2.7 is scheduled for 2020. Currently more and more Python project are switching to Python 3 or 2/3 compatible code. The issue of migrating Kodi’s built-in Python interpreter to Python 3.x was brought up on the Kodi forum several times. Now, thanks to a successful GSOC 2017 project, we have a working Python 3 interpreter for Kodi. That is why on Kodi DevCon 2017 Team Kodi decided that we will switch to Python 3 in the future Kodi release (v.19 preliminarily).&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 3.x versions are not backward-compatible with Python 2.x, so we decided to urge addon developers to start porting their addons to Python 3 by making the addons compatible with both Python 2 and 3 and submitting them to the official repo. This way, when Kodi with Python 3 is released, we won’t have a situation when we have no working addons.&lt;br /&gt;
&lt;br /&gt;
== The Process ==&lt;br /&gt;
&lt;br /&gt;
* Starting from Kodi 18 (Leia), only addons that are compatible with both Python 2 and 3 will be accepted to the official addon repository.&lt;br /&gt;
* We will provide Kodi builds with Python 3 so that addon developers can tests if their addons are really compatible with Python 3.&lt;br /&gt;
* A thread will be created on the Kodi forum so that addon devs can get help with their migration process.&lt;br /&gt;
&lt;br /&gt;
== Python 3 And 2 Differences ==&lt;br /&gt;
&lt;br /&gt;
Below is a brief overview of the main differences between Python 3 and 2.&lt;br /&gt;
&lt;br /&gt;
=== Unicode strings by default ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 built-in &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds the sequence of bytes so it can be used to store both binary data and textual data in ASCII or any of 8-bit fixed-length encodings (there were plenty). Python 2 also has &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; type that can store text in various writing systems. A minimal unit of a &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; object is a Unicode codepoint (a Unicode character). Both &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unicode&amp;lt;/code&amp;gt; objects can be mixed and matched together, for example, concatenated using &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; operator.&lt;br /&gt;
&lt;br /&gt;
In Python 3 &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; type holds Unicode characters, and for binary data a new &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; type was added. This type was also added to Python 2.7 to simplify porting to Python 3 but in Python 2.7 bytes is simply an alias for &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; and bytes types are incompatible, and an attempt to use both together will result in &amp;lt;code&amp;gt;TypeError&amp;lt;/code&amp;gt; exception. A &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; object can be converted to &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; using .decode() method, and a &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; is converted to &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; using .encode() method.&lt;br /&gt;
&lt;br /&gt;
=== Absolute Import ===&lt;br /&gt;
Python 3 uses so called “absolute import” and you can no longer import modules from inside a package using only a module name. You need to either to use either a fully qualified name or a “dotted” notation.&lt;br /&gt;
&lt;br /&gt;
Let’s assume that you have a foo package that contains bar and spam modules, and you need to import bar module from spam. In Python 2 you can do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But in Python 3 you need to use either&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import foo.bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from . import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating Point Division ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 applying division operator to int numbers produces int result. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 / 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Python 3 division operator always gives you a float result.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4/3&lt;br /&gt;
1.3333333333333333&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get an int result you need to use integer division operator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 // 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Print Function ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 print statement has been replaced with print() function. This is not very relevant to Kodi because using print in Python addons is discouraged and xbmc.log() function should be used to write messages to the Kodi log.&lt;br /&gt;
&lt;br /&gt;
=== Default Iterators ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 most function and methods that produce sequences return iterators instead of lists. For example, range() function and .items(), .keys(), .values() of dict type produce iterators instead of lists, and their Python 2 analogues — xrange() function and .iter* methods of dict type — have been removed.&lt;br /&gt;
&lt;br /&gt;
=== No long Integers ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 long integer type has been removed and int type can now hold a number of arbitrary length.&lt;br /&gt;
&lt;br /&gt;
Those are only some of the differences between Python 2 and 3. For a more complete list see [https://docs.python.org/3.6/whatsnew/3.0.html official Python documentation].&lt;br /&gt;
&lt;br /&gt;
== Some Useful Information ==&lt;br /&gt;
&lt;br /&gt;
As it was said above, Python 3 includes a number of incompatible changes, so to avoid situation when after upgrading Kodi for Python 3 support most Python addons will be broken developers should start to port their addons to be compatible with both Python 2 and 3. This is not a trivial task but fortunately there are a number of tools and recommendations to simplify this process. Here I’ll give you some advice and information about tools that will simplify creating portable code that runs on both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
=== Know Your Strings! ===&lt;br /&gt;
&lt;br /&gt;
This is the most problematic part of porting Python 2 code to Python 3 so I put it first. One of the most notable differences between Python 2 and 3 is clear separation between “textual” and “binary” strings, that is, between textual data and their binary representation. This difference is often difficult to understand, especially for novice developers (not only in Python), and the fact that in Python 2 you can mix together str (binary data) and unicode (textual data) adds to that difficulty.&lt;br /&gt;
&lt;br /&gt;
There are many explanations in the Internet, but here are the most basic things about strings that you need to know:&lt;br /&gt;
&lt;br /&gt;
“Textual” or Unicode strings (unicode in Python 2 and str in Python 3) hold text as a sequence of characters. A minimal unit in such strings is a Unicode character — an abstract entity that represent an alphabet symbol, a punctuation sign or other symbol included in the Unicode character table. Of course, such symbols have concrete internal binary representation (a computer is a binary machine after all), but this representation is not relevant to us. All you need to know is that “textual” strings contain text units without being tied to concrete binary representation.&lt;br /&gt;
&lt;br /&gt;
Unlike Unicode strings, binary strings (str in Python 2 and bytes in both Python 2 and 3) hold binary data, and a minimal unit of such strings is a byte or 8 bits. Historically, in Python 2 such strings are used for textual data encoded in ASCII or other 1-byte fixed-length encoding (e.g. Windows 1251 for Cyrillic alphabets). However, this approach has its limitation, that is why unicode type was introduced in Python 2, and in Python 3 it was renamed to str and made a default container for textual data.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 2 allows to mix and match Unicode and binary strings in the same context and this creates big problems when porting Python 2 code to Python 3. So in order to successfully port your code to Python 3 you need to carefully consider how textual data are processed in your addon. The following recommendations will help you avoid problems when writing Python 2/3 compatible code.&lt;br /&gt;
&lt;br /&gt;
=== Avoid using binary strings for text ===&lt;br /&gt;
&lt;br /&gt;
Store all your text as Unicode strings. This means that all binary strings received from external sources (textual files, websites, various APIs) need to be decoded using appropriate encoding (UTF-8 in most cases). If you need to use strings literals (although using hardcoded strings for user-facing text in Kodi is strongly discouraged), they need to be defined as unicode strings as well. You can use either&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
at the beginning of your modules to enable unicode strings by default as in Python 3 or u-strings, e.g. &amp;lt;code&amp;gt;u&#039;foo&#039;&amp;lt;/code&amp;gt; (Python 3 understands them too) — it doesn&#039;t really matter as long as you are doing it consistently.&lt;br /&gt;
&lt;br /&gt;
=== Know the libraries you are using ===&lt;br /&gt;
Working with Python Standard Library and third-party libraries (including Kodi Python API) you should know that types their functions and methods expect and what types they return. For example, in popular requests library Response.text property returns a Unicode string and Response.content returns a binary string.&lt;br /&gt;
&lt;br /&gt;
If a function/method/property returns a binary string, you need to decode it to a Unicode string using .decode() method. Don’t use unicode class constructor because unicode type does not exist in Python 3.&lt;br /&gt;
&lt;br /&gt;
If you are reading textual files from disk, it is better to use io.open() instead of built-in open(). io.open() can decode file contents to Unicode using specified encoding and works identically both in Python 2 and 3. Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import io&lt;br /&gt;
&lt;br /&gt;
with io.open(&#039;foo.txt&#039;, &#039;r&#039;, encoding=&#039;utf-8&#039;) as fo:&lt;br /&gt;
   text = fo.read()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Potential pitfalls ===&lt;br /&gt;
&lt;br /&gt;
When writing Python 2/3-compatible code or converting existing Python 2 codebase to compatible code you should pay attention to the following Python language constructions where TypeError exceptions may happen because of incompatible string types if you don’t get your strings in order:&lt;br /&gt;
&lt;br /&gt;
* String concatenations with + operator (&amp;lt;code&amp;gt;&#039;foo&#039; + &#039;bar&#039;&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String formatting — both “old style” (&amp;lt;code&amp;gt;&#039;foo %s&#039; % &#039;bar&#039;&amp;lt;/code&amp;gt;) and “new style” (&amp;lt;code&amp;gt;&#039;foo {}&#039;.format(&#039;bar&#039;)&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String joining (&amp;lt;code&amp;gt;&#039;, &#039;.join([&#039;foo&#039;, &#039;bar&#039;])&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
In all those cases always make sure that you work with Unicode strings only.&lt;br /&gt;
Another source of subtle bugs is functions and methods that accept and return binary strings (str type) in Python 2  but Unicode strings in Python 3 (again, str type but with different properties). You can use the following utility functions to “normalize” strings that are provided to such functions/methods and received from them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
__all__ = [&#039;PY2&#039;, &#039;py2_encode&#039;, &#039;py2_decode&#039;]&lt;br /&gt;
&lt;br /&gt;
PY2 = sys.version_info[0] == 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_encode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Encode Python 2 ``unicode`` to ``str``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.   &lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, unicode):&lt;br /&gt;
       s = s.encode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_decode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Decode Python 2 ``str`` to ``unicode``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, str):&lt;br /&gt;
       s = s.decode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Helper Libraries and Tools ==&lt;br /&gt;
&lt;br /&gt;
=== 2to3 ===&lt;br /&gt;
&lt;br /&gt;
[https://docs.python.org/2/library/2to3.html 2to3] script is created by Python developers to help converting existing Python 2 code to Python 3. On Windows it is included in Python distribution (Tools subfolder) but on other OSes you man need to install it separately. For example, on Ubuntu it is included in python-examples package. Note that this script is created for conversion from Python 2 to 3, not for writing portable code, so you need to treat its output with care.&lt;br /&gt;
&lt;br /&gt;
=== Modernize ===&lt;br /&gt;
&lt;br /&gt;
https://python-modernize.readthedocs.io/en/latest/ Modernize] script works on top of 2to3 and is supposed to help you to convert your existing Python 2 code to Python 2/3-compatible. However, in my experiments it did not work reliably even in simple cases so I cannot recommend it for usage.&lt;br /&gt;
&lt;br /&gt;
=== Six ===&lt;br /&gt;
&lt;br /&gt;
[https://pythonhosted.org/six/ Six] was the first library developed to simplify Python 2 to 3 migration. It provides a set of wrappers that hide differences between Python 2 and 3 behind its API. It is less intrusive than the following alternative because it does not monkey-patch built-in names, but in order to use Six library effectively you need to learn its API. Six can be used both for writing new Python 2/3-compatible addons and converting existing ones, but it requires good knowledge of Python 2/3 differences to pick necessary Six features that address specific differences.&lt;br /&gt;
&lt;br /&gt;
Six library is included in the Kodi addon repository as &#039;&#039;&#039;script.module.six addon&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Future ===&lt;br /&gt;
&lt;br /&gt;
[http://python-future.org/ Future] library, like Six, was created to simplify porting existing Python 2 code to 3. But it uses a different approach than Six. Future monkey-patches built-in Python objects to make Python 2 behave like Python 3. The advantage of such approach is that code written using Future is close to idiomatic Python 3 and requires little re-work if you decide to drop Python 2 support in the future. However, such approach may cause problems in some rare edge-cases.&lt;br /&gt;
&lt;br /&gt;
Future library also includes &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; command-line utility for converting existing Python 2 code to 2/3-compatible and in my experiments this utility showed good results.&lt;br /&gt;
Future library (without additional utilities) is included in the Kodi addon repository as script.module.future addon.&lt;br /&gt;
&lt;br /&gt;
=== PyCharm ===&lt;br /&gt;
&lt;br /&gt;
PyCharm, except for being a really good Python IDE, also provides code compatibility inspection that helps you write Python 2/3-portable code. Open &#039;&#039;&#039;Settings&#039;&#039;&#039; (Alt+F7) &amp;gt; &#039;&#039;&#039;Editor&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Inspections&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Python&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Code compatibility inspections&#039;&#039;&#039; and check Python version that you want to support.&lt;br /&gt;
&lt;br /&gt;
PyCharm Community Edition is free and provides all features you need for creating Python addons for Kodi.&lt;br /&gt;
&lt;br /&gt;
== Writing Portable Code ==&lt;br /&gt;
&lt;br /&gt;
Here I’ll give you some tips about how to write portable code:&lt;br /&gt;
&lt;br /&gt;
* Learn the differences between Python 2 and 3. You need to know at least the most important differences between the two major Python versions.&lt;br /&gt;
&lt;br /&gt;
* Use version control system — git or mercurial — to track changes in your code. If you are porting existing code, do it in a separate branch.&lt;br /&gt;
&lt;br /&gt;
* No matter if you are going to write a brand new addon or to port existing addon to Python 3, carefully choose your tools. It is totally possible to write portable code without any helper tools and libraries, but you need to know what you are doing. However, in most cases I’d recommend you to use Future library and its utilities. Carefully read Future documentation.&lt;br /&gt;
&lt;br /&gt;
* Put the following line at the beginning of all your modules:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will enable respective Python 3 features in your code. You don’t need to import print_function (another Python 3 feature) because in Kodi addons you should to use xbmc.log() to write messages to the Kodi log file.&lt;br /&gt;
&lt;br /&gt;
=== Writing New Addons ===&lt;br /&gt;
&lt;br /&gt;
Check the [http://python-future.org/quickstart.html#if-you-are-writing-code-from-scratch Quick Start Guide] section of Future library documentation. You can also use Six library, but, as it was said previously, you need to learn its API to pick the necessary features to address specific Python version differences, while Future allows to write your code in (almost) idiomatic Python 3.&lt;br /&gt;
&lt;br /&gt;
A brief procedure for writing new Python 2/3-compatible addons with Future library:&lt;br /&gt;
&lt;br /&gt;
# Create a new virtual environment with Python 3 interpreter and activate it.&lt;br /&gt;
# Install Future library: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Point your IDE (Integrated Development Environment) to that environment. For example, in PyCharm: &#039;&#039;&#039;File&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Setting&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project Interpreter&#039;&#039;&#039;.&lt;br /&gt;
# Put the following line at the beginning of your Python code:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
from builtins import *&lt;br /&gt;
from future import standard_library&lt;br /&gt;
standard_library.install_aliases()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Write your addon using Python 3 syntax and standard library names.&lt;br /&gt;
&lt;br /&gt;
=== Porting Existing Addons ===&lt;br /&gt;
&lt;br /&gt;
A brief procedure for porting existing code to Python 3-compatible with Future library:&lt;br /&gt;
&lt;br /&gt;
# Install Future library into your working Python 2 virtual environment: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; utility to convert all your scripts and modules to portable code.&lt;br /&gt;
&lt;br /&gt;
Test your new or converted addon in Kodi with Python 2 interpreter and fix all found issues. After that test the addon in Kodi with Python 3 interpreter and again fix all found issues.&lt;br /&gt;
You can use [https://github.com/romanvm/kodi.web-pdb Web-PDB] debugger for troubleshooting issues in your code. It is compatible with both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* Python 2 and 3 differences: https://docs.python.org/3.6/whatsnew/3.0.html&lt;br /&gt;
* Future library documentation: http://python-future.org/&lt;br /&gt;
* Six library documentation: https://pythonhosted.org/six/&lt;br /&gt;
* Kodi test builds with Python 3 for Windows: http://mirrors.xbmc.org/test-builds/windows/win32/&lt;br /&gt;
* Kodi test builds with Python 3 for Linux Ubuntu: https://launchpad.net/~wsnipex/+archive/ubuntu/kodi-python3/+packages&lt;br /&gt;
* “Python 3 migration” section on the Kodi official forum: https://forum.kodi.tv/forumdisplay.php?fid=281&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
	<entry>
		<id>https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132211</id>
		<title>General information about migration to Python 3</title>
		<link rel="alternate" type="text/html" href="https://kodi.wiki/index.php?title=General_information_about_migration_to_Python_3&amp;diff=132211"/>
		<updated>2018-01-04T11:22:46Z</updated>

		<summary type="html">&lt;p&gt;Roman V M: Created page with &amp;quot;== Overview ==  Python 3 was released 9 years ago and EOL for Python 2.7 is scheduled for 2020. Currently more and more Python project are switching to Python 3 or 2/3 compati...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Python 3 was released 9 years ago and EOL for Python 2.7 is scheduled for 2020. Currently more and more Python project are switching to Python 3 or 2/3 compatible code. The issue of migrating Kodi’s built-in Python interpreter to Python 3.x was brought up on the Kodi forum several times. Now, thanks to a successful GSOC 2017 project, we have a working Python 3 interpreter for Kodi. That is why on Kodi DevCon 2017 Team Kodi decided that we will switch to Python 3 in the future Kodi release (v.19 preliminarily).&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 3.x versions are not backward-compatible with Python 2.x, so we decided to urge addon developers to start porting their addons to Python 3 by making the addons compatible with both Python 2 and 3 and submitting them to the official repo. This way, when Kodi with Python 3 is released, we won’t have a situation when we have no working addons.&lt;br /&gt;
&lt;br /&gt;
== The Process ==&lt;br /&gt;
&lt;br /&gt;
* Starting from Kodi 18 (Leia), only addons that are compatible with both Python 2 and 3 will be accepted to the official addon repository.&lt;br /&gt;
* We will provide Kodi builds with Python 3 so that addon developers can tests if their addons are really compatible with Python 3.&lt;br /&gt;
* A thread will be created on the Kodi forum so that addon devs can get help with their migration process.&lt;br /&gt;
&lt;br /&gt;
== Python 3 And 2 Differences ==&lt;br /&gt;
&lt;br /&gt;
Below is a brief overview of the main differences between Python 3 and 2.&lt;br /&gt;
&lt;br /&gt;
=== Unicode strings by default ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 built-in str type holds the sequence of bytes so it can be used to store both binary data and textual data in ASCII or any of 8-bit fixed-length encodings (there were plenty). Python 2 also has unicode type that can store text in various writing systems. A minimal unit of a unicode object is a Unicode codepoint (a Unicode character). Both str and unicode objects can be mixed and matched together, for example, concatenated using + operator.&lt;br /&gt;
&lt;br /&gt;
In Python 3 str type holds Unicode characters, and for binary data a new bytes type was added. This type was also added to Python 2.7 to simplify porting to Python 3 but in Python 2.7 bytes is simply an alias for str. The str and bytes types are incompatible, and an attempt to use both together will result in TypeError exception. A bytes object can be converted to str using .decode() method, and a str is converted to bytes using .encode() method.&lt;br /&gt;
&lt;br /&gt;
=== Absolute Import ===&lt;br /&gt;
Python 3 uses so called “absolute import” and you can no longer import modules from inside a package using only a module name. You need to either to use either a fully qualified name or a “dotted” notation.&lt;br /&gt;
&lt;br /&gt;
Let’s assume that you have a foo package that contains bar and spam modules, and you need to import bar module from spam. In Python 2 you can do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But in Python 3 you need to use either&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import foo.bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from . import bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floating Point Division ===&lt;br /&gt;
&lt;br /&gt;
In Python 2 applying division operator to int numbers produces int result. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 / 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Python 3 division operator always gives you a float result.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4/3&lt;br /&gt;
1.3333333333333333&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get an int result you need to use integer division operator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; 4 // 3&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Print Function ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 print statement has been replaced with print() function. This is not very relevant to Kodi because using print in Python addons is discouraged and xbmc.log() function should be used to write messages to the Kodi log.&lt;br /&gt;
&lt;br /&gt;
=== Default Iterators ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 most function and methods that produce sequences return iterators instead of lists. For example, range() function and .items(), .keys(), .values() of dict type produce iterators instead of lists, and their Python 2 analogues — xrange() function and .iter* methods of dict type — have been removed.&lt;br /&gt;
&lt;br /&gt;
=== No long Integers ===&lt;br /&gt;
&lt;br /&gt;
In Python 3 long integer type has been removed and int type can now hold a number of arbitrary length.&lt;br /&gt;
&lt;br /&gt;
Those are only some of the differences between Python 2 and 3. For a more complete list see [https://docs.python.org/3.6/whatsnew/3.0.html official Python documentation].&lt;br /&gt;
&lt;br /&gt;
== Some Useful Information ==&lt;br /&gt;
&lt;br /&gt;
As it was said above, Python 3 includes a number of incompatible changes, so to avoid situation when after upgrading Kodi for Python 3 support most Python addons will be broken developers should start to port their addons to be compatible with both Python 2 and 3. This is not a trivial task but fortunately there are a number of tools and recommendations to simplify this process. Here I’ll give you some advice and information about tools that will simplify creating portable code that runs on both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
=== Know Your Strings! ===&lt;br /&gt;
&lt;br /&gt;
This is the most problematic part of porting Python 2 code to Python 3 so I put it first. One of the most notable differences between Python 2 and 3 is clear separation between “textual” and “binary” strings, that is, between textual data and their binary representation. This difference is often difficult to understand, especially for novice developers (not only in Python), and the fact that in Python 2 you can mix together str (binary data) and unicode (textual data) adds to that difficulty.&lt;br /&gt;
&lt;br /&gt;
There are many explanations in the Internet, but here are the most basic things about strings that you need to know:&lt;br /&gt;
&lt;br /&gt;
“Textual” or Unicode strings (unicode in Python 2 and str in Python 3) hold text as a sequence of characters. A minimal unit in such strings is a Unicode character — an abstract entity that represent an alphabet symbol, a punctuation sign or other symbol included in the Unicode character table. Of course, such symbols have concrete internal binary representation (a computer is a binary machine after all), but this representation is not relevant to us. All you need to know is that “textual” strings contain text units without being tied to concrete binary representation.&lt;br /&gt;
&lt;br /&gt;
Unlike Unicode strings, binary strings (str in Python 2 and bytes in both Python 2 and 3) hold binary data, and a minimal unit of such strings is a byte or 8 bits. Historically, in Python 2 such strings are used for textual data encoded in ASCII or other 1-byte fixed-length encoding (e.g. Windows 1251 for Cyrillic alphabets). However, this approach has its limitation, that is why unicode type was introduced in Python 2, and in Python 3 it was renamed to str and made a default container for textual data.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Python 2 allows to mix and match Unicode and binary strings in the same context and this creates big problems when porting Python 2 code to Python 3. So in order to successfully port your code to Python 3 you need to carefully consider how textual data are processed in your addon. The following recommendations will help you avoid problems when writing Python 2/3 compatible code.&lt;br /&gt;
&lt;br /&gt;
=== Avoid using binary strings for text ===&lt;br /&gt;
&lt;br /&gt;
Store all your text as Unicode strings. This means that all binary strings received from external sources (textual files, websites, various APIs) need to be decoded using appropriate encoding (UTF-8 in most cases). If you need to use strings literals (although using hardcoded strings for user-facing text in Kodi is strongly discouraged), they need to be defined as unicode strings as well. You can use either&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
at the beginning of your modules to enable unicode strings by default as in Python 3 or u-strings, e.g. &amp;lt;code&amp;gt;u&#039;foo&#039;&amp;lt;/code&amp;gt; (Python 3 understands them too) — it doesn&#039;t really matter as long as you are doing it consistently.&lt;br /&gt;
&lt;br /&gt;
=== Know the libraries you are using ===&lt;br /&gt;
Working with Python Standard Library and third-party libraries (including Kodi Python API) you should know that types their functions and methods expect and what types they return. For example, in popular requests library Response.text property returns a Unicode string and Response.content returns a binary string.&lt;br /&gt;
&lt;br /&gt;
If a function/method/property returns a binary string, you need to decode it to a Unicode string using .decode() method. Don’t use unicode class constructor because unicode type does not exist in Python 3.&lt;br /&gt;
&lt;br /&gt;
If you are reading textual files from disk, it is better to use io.open() instead of built-in open(). io.open() can decode file contents to Unicode using specified encoding and works identically both in Python 2 and 3. Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import io&lt;br /&gt;
&lt;br /&gt;
with io.open(&#039;foo.txt&#039;, &#039;r&#039;, encoding=&#039;utf-8&#039;) as fo:&lt;br /&gt;
   text = fo.read()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Potential pitfalls ===&lt;br /&gt;
&lt;br /&gt;
When writing Python 2/3-compatible code or converting existing Python 2 codebase to compatible code you should pay attention to the following Python language constructions where TypeError exceptions may happen because of incompatible string types if you don’t get your strings in order:&lt;br /&gt;
&lt;br /&gt;
* String concatenations with + operator (&amp;lt;code&amp;gt;&#039;foo&#039; + &#039;bar&#039;&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String formatting — both “old style” (&amp;lt;code&amp;gt;&#039;foo %s&#039; % &#039;bar&#039;&amp;lt;/code&amp;gt;) and “new style” (&amp;lt;code&amp;gt;&#039;foo {}&#039;.format(&#039;bar&#039;)&amp;lt;/code&amp;gt;).&lt;br /&gt;
* String joining (&amp;lt;code&amp;gt;&#039;, &#039;.join([&#039;foo&#039;, &#039;bar&#039;])&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
In all those cases always make sure that you work with Unicode strings only.&lt;br /&gt;
Another source of subtle bugs is functions and methods that accept and return binary strings (str type) in Python 2  but Unicode strings in Python 3 (again, str type but with different properties). You can use the following utility functions to “normalize” strings that are provided to such functions/methods and received from them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
__all__ = [&#039;PY2&#039;, &#039;py2_encode&#039;, &#039;py2_decode&#039;]&lt;br /&gt;
&lt;br /&gt;
PY2 = sys.version_info[0] == 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_encode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Encode Python 2 ``unicode`` to ``str``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.   &lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, unicode):&lt;br /&gt;
       s = s.encode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def py2_decode(s, encoding=&#039;utf-8&#039;):&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Decode Python 2 ``str`` to ``unicode``&lt;br /&gt;
&lt;br /&gt;
   In Python 3 the string is not changed.&lt;br /&gt;
   &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   if PY2 and isinstance(s, str):&lt;br /&gt;
       s = s.decode(encoding)&lt;br /&gt;
   return s&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Helper Libraries and Tools ==&lt;br /&gt;
&lt;br /&gt;
=== 2to3 ===&lt;br /&gt;
&lt;br /&gt;
[https://docs.python.org/2/library/2to3.html 2to3] script is created by Python developers to help converting existing Python 2 code to Python 3. On Windows it is included in Python distribution (Tools subfolder) but on other OSes you man need to install it separately. For example, on Ubuntu it is included in python-examples package. Note that this script is created for conversion from Python 2 to 3, not for writing portable code, so you need to treat its output with care.&lt;br /&gt;
&lt;br /&gt;
=== Modernize ===&lt;br /&gt;
&lt;br /&gt;
https://python-modernize.readthedocs.io/en/latest/ Modernize] script works on top of 2to3 and is supposed to help you to convert your existing Python 2 code to Python 2/3-compatible. However, in my experiments it did not work reliably even in simple cases so I cannot recommend it for usage.&lt;br /&gt;
&lt;br /&gt;
=== Six ===&lt;br /&gt;
&lt;br /&gt;
[https://pythonhosted.org/six/ Six] was the first library developed to simplify Python 2 to 3 migration. It provides a set of wrappers that hide differences between Python 2 and 3 behind its API. It is less intrusive than the following alternative because it does not monkey-patch built-in names, but in order to use Six library effectively you need to learn its API. Six can be used both for writing new Python 2/3-compatible addons and converting existing ones, but it requires good knowledge of Python 2/3 differences to pick necessary Six features that address specific differences.&lt;br /&gt;
&lt;br /&gt;
Six library is included in the Kodi addon repository as &#039;&#039;&#039;script.module.six addon&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Future ===&lt;br /&gt;
&lt;br /&gt;
[http://python-future.org/ Future] library, like Six, was created to simplify porting existing Python 2 code to 3. But it uses a different approach than Six. Future monkey-patches built-in Python objects to make Python 2 behave like Python 3. The advantage of such approach is that code written using Future is close to idiomatic Python 3 and requires little re-work if you decide to drop Python 2 support in the future. However, such approach may cause problems in some rare edge-cases.&lt;br /&gt;
&lt;br /&gt;
Future library also includes &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; command-line utility for converting existing Python 2 code to 2/3-compatible and in my experiments this utility showed good results.&lt;br /&gt;
Future library (without additional utilities) is included in the Kodi addon repository as script.module.future addon.&lt;br /&gt;
&lt;br /&gt;
=== PyCharm ===&lt;br /&gt;
&lt;br /&gt;
PyCharm, except for being a really good Python IDE, also provides code compatibility inspection that helps you write Python 2/3-portable code. Open &#039;&#039;&#039;Settings&#039;&#039;&#039; (Alt+F7) &amp;gt; &#039;&#039;&#039;Editor&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Inspections&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Python&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Code compatibility inspections&#039;&#039;&#039; and check Python version that you want to support.&lt;br /&gt;
&lt;br /&gt;
PyCharm Community Edition is free and provides all features you need for creating Python addons for Kodi.&lt;br /&gt;
&lt;br /&gt;
== Writing Portable Code ==&lt;br /&gt;
&lt;br /&gt;
Here I’ll give you some tips about how to write portable code:&lt;br /&gt;
&lt;br /&gt;
* Learn the differences between Python 2 and 3. You need to know at least the most important differences between the two major Python versions.&lt;br /&gt;
&lt;br /&gt;
* Use version control system — git or mercurial — to track changes in your code. If you are porting existing code, do it in a separate branch.&lt;br /&gt;
&lt;br /&gt;
* No matter if you are going to write a brand new addon or to port existing addon to Python 3, carefully choose your tools. It is totally possible to write portable code without any helper tools and libraries, but you need to know what you are doing. However, in most cases I’d recommend you to use Future library and its utilities. Carefully read Future documentation.&lt;br /&gt;
&lt;br /&gt;
* Put the following line at the beginning of all your modules:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will enable respective Python 3 features in your code. You don’t need to import print_function (another Python 3 feature) because in Kodi addons you should to use xbmc.log() to write messages to the Kodi log file.&lt;br /&gt;
&lt;br /&gt;
=== Writing New Addons ===&lt;br /&gt;
&lt;br /&gt;
Check the [http://python-future.org/quickstart.html#if-you-are-writing-code-from-scratch Quick Start Guide] section of Future library documentation. You can also use Six library, but, as it was said previously, you need to learn its API to pick the necessary features to address specific Python version differences, while Future allows to write your code in (almost) idiomatic Python 3.&lt;br /&gt;
&lt;br /&gt;
A brief procedure for writing new Python 2/3-compatible addons with Future library:&lt;br /&gt;
&lt;br /&gt;
# Create a new virtual environment with Python 3 interpreter and activate it.&lt;br /&gt;
# Install Future library: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Point your IDE (Integrated Development Environment) to that environment. For example, in PyCharm: &#039;&#039;&#039;File&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Setting&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Project Interpreter&#039;&#039;&#039;.&lt;br /&gt;
# Put the following line at the beginning of your Python code:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from __future__ import absolute_import, division, unicode_literals&lt;br /&gt;
from builtins import *&lt;br /&gt;
from future import standard_library&lt;br /&gt;
standard_library.install_aliases()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Write your addon using Python 3 syntax and standard library names.&lt;br /&gt;
&lt;br /&gt;
=== Porting Existing Addons ===&lt;br /&gt;
&lt;br /&gt;
A brief procedure for porting existing code to Python 3-compatible with Future library:&lt;br /&gt;
&lt;br /&gt;
# Install Future library into your working Python 2 virtual environment: &amp;lt;code&amp;gt;pip install future&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;futurize&amp;lt;/code&amp;gt; utility to convert all your scripts and modules to portable code.&lt;br /&gt;
&lt;br /&gt;
Test your new or converted addon in Kodi with Python 2 interpreter and fix all found issues. After that test the addon in Kodi with Python 3 interpreter and again fix all found issues.&lt;br /&gt;
You can use [https://github.com/romanvm/kodi.web-pdb Web-PDB] debugger for troubleshooting issues in your code. It is compatible with both Python 2 and 3.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* Python 2 and 3 differences: https://docs.python.org/3.6/whatsnew/3.0.html&lt;br /&gt;
* Future library documentation: http://python-future.org/&lt;br /&gt;
* Six library documentation: https://pythonhosted.org/six/&lt;br /&gt;
* Kodi test builds with Python 3 for Windows: http://mirrors.xbmc.org/test-builds/windows/win32/&lt;br /&gt;
* Kodi test builds with Python 3 for Linux Ubuntu: https://launchpad.net/~wsnipex/+archive/ubuntu/kodi-python3/+packages&lt;br /&gt;
* “Python 3 migration” section on the Kodi official forum: https://forum.kodi.tv/forumdisplay.php?fid=281&lt;/div&gt;</summary>
		<author><name>Roman V M</name></author>
	</entry>
</feed>