Page 1 of 4
Importing python libraries to run script but which libraries?
Posted: Wed Apr 04, 2018 4:11 pm
by jachin99
I have found a script that finds movies from my collection, then scours youtube and downloads trailers for all of them supposedly. I have a basic understanding of how to import a library in EG manually (Drop the library into the lib27 packages folder), and I'm trying to work off of the import statement from the script. I have added some of the correct libraries but I'm having trouble finding others. In particular, I'm not finding the system library from python's site, and when I do find libraries whose names match or sound similar, I don't know how to be sure that I am grabbing the correct library referenced in the script. How can I be sure I grabbed the correct libraries? Here is the script:
Code: Select all
import sys
import requests
import urllib
import json
import ConfigParser
import glob
import os
from pytube import YouTube
config = ConfigParser.RawConfigParser()
config.read('trailers.ini')
embyapi = ""
embykey = ""
embyusr = ""
h = 0
i = 0
j = 0
k = 0
if config.has_option('emby', 'api'):
embyapi = config.get('emby', 'api')
else:
embyerror = "No Emby URL in Config File.\n"
if config.has_option('emby', 'key'):
embykey = config.get('emby', 'key')
else:
embyerror += "No Emby API Key in Config File.\n"
if config.has_option('emby', 'usr'):
embyusr = config.get('emby', 'usr')
else:
embyerror += "No Emby User ID in Config File."
if config.has_option('emby', 'dirfrom'):
embydirf = config.get('emby', 'dirfrom')
else:
embydirf = ""
if config.has_option('emby', 'dirto'):
embydirt = config.get('emby', 'dirto')
else:
embydirt = ""
if len(embyapi) == 0 or len(embykey) == 0 or len(embyusr) == 0:
print(embyerror)
sys.exit()
if embyapi[-1] != "/":
embyapi += "/"
url = embyapi + "Users/%s/Items?IncludeItemTypes=Movie&Recursive=true&StartIndex=0&format=json&fields=RemoteTrailers,Path" % (embyusr)
headers = {
'content-type': 'application/json',
'Authorization': 'MediaBrowser',
'UserId': embyusr,
'Client': 'EmbyTrailers',
'Device': 'Python Script',
'DeviceId': 'xxx',
'Version': '1.0.0.0',
'X-MediaBrowser-Token': embykey,
}
emby = requests.get(url, headers = headers)
films = json.loads(emby.content)
if not 'Name' in films['Items'][0]:
print
print("No Films Found")
else:
for film in films['Items']:
if film['LocalTrailerCount'] == 0:
h += 1
fulpath = film['Path'].encode("utf-8")
if embydirf != "" and embydirt != "":
fulpath = fulpath.replace(embydirf, embydirt, 1)
fulpath = os.path.normpath(fulpath.replace('\\', os.sep))
basefil = os.path.basename(fulpath)
basedir = os.path.dirname(fulpath)
trail = os.path.splitext(basefil)[0]
if trail[-3:-1] == "CD":
trail = trail[:-4]
if basedir[-1] != os.sep:
basedir += os.sep
if len(glob.glob(r"%s%s%s" % (basedir, trail, "-trailer*"))) == 0:
download = True
i += 1
for trailer in film['RemoteTrailers']:
if download:
try:
yt = YouTube(trailer['Url'].encode("utf-8"))
yt.set_filename(trail + "-trailer")
video = yt.filter('mp4')[-1]
video.download(basedir)
except Exception, e:
print(trail + " - " + trailer['Url'].encode("utf-8") + " - " + str(e))
if len(glob.glob(r"%s%s%s" % (basedir, trail, "-trailer*"))) > 0:
download = False
j += 1
if download:
k += 1
print("Emby thinks %s Films are Missing Trailers" % (h))
print("%s Films Actually Missing Trailers" % (i))
print("Downloaded %s Trailers" % (j))
print("Unable to Download %s Trailers" % (k))
Re: Importing python libraries to run script but which libraries?
Posted: Wed Apr 04, 2018 5:54 pm
by jachin99
Alright, Trying to answer my own question here. If a script is trying to import a module that is not a part of the standard python library, then the statement would have to specify where it is trying to import that module from, correct? For example, if I'm importing a module from a libarary that is not part of the standard python 27 library package, the statment would look something like
from pytube import youtube
If that is true then every other module this script is trying to import should be a part of the standard python library? Tieing this into EventGhost, as long as those standard python modules are compatable with EG then those import statements should be valid, and work in EG BUT what about the youtube library? I have added it to my lib27 packages folder but I'm not sure if that is a valid place to put an entire library without actually installing python on the machine. I'm looking at this as more of a learning experience, and there is a good chance I won't even use this to accomplish what I need it to do but if it works out then thats ok too. I thought I would ask here to verify my thoughts.
Re: Importing python libraries to run script but which libraries?
Posted: Fri Apr 06, 2018 3:52 pm
by kgschlosser
you want to put it into the site-packages folder
if the directory for the package is named pytube and what you are trying to access is either inside of the __ini__.py file in the pytube directory. or has been imported in that file then you can do this
or you can do this as well
Now. if you do not want to place it into your site-packages folder. and would rather have it located somewhere else. you need to add the parent directory to the list of directories that python searches.
Code: Select all
import sys
sys.path.append(r'c:\library_parent_directory\library')
and here is a spin on it. If it is an egg. (folder ends with .egg) and there is a .pth file in the parent folder then you either need to add a new site or you need to add the path to sys.path and process the .pth file.
Code: Select all
import site
site.addsite(r'c:\library_parent_directory\library')
to add the path and process the pth file
Code: Select all
import sys
import pkg_resources
sys.path.append(r'c:\library_parent_directory\library')
pkg_resources.require('library')
Re: Importing python libraries to run script but which libraries?
Posted: Fri Apr 06, 2018 3:58 pm
by kgschlosser
just as a suggestion
Code: Select all
emby = requests.get(url, headers = headers)
films = json.loads(emby.content)
the requests library has a convince method in the Response class..
Code: Select all
emby = requests.get(url, headers = headers)
films = emby.json()
But you still should always have some error handling any time you are dealing with data conversions. you could get something that is all mucked up
Code: Select all
try:
emby = requests.get(url, headers = headers)
films = emby.json()
except (requests.HTTPError, ValueError):
eg.StopMacro()
eg.Exit()
in the example above. the requests.HTTPError covers all exceptions generated from requests dealing with the HTTP connection. the ValueError covers the json data conversion in the event it fails. This will stop the current macro and exit the script. you can have it print some kind of information if you wanted informing you of the error.
Re: Importing python libraries to run script but which libraries?
Posted: Tue May 08, 2018 1:00 am
by jachin99
kgschlosser wrote: Fri Apr 06, 2018 3:58 pm
just as a suggestion
Code: Select all
emby = requests.get(url, headers = headers)
films = json.loads(emby.content)
I'm guessing this puts together the request url, and would replace this bit of code?
Code: Select all
url = embyapi + "Users/%s/Items?IncludeItemTypes=Movie&Recursive=true&StartIndex=0&format=json&fields=RemoteTrailers,Path" % (embyusr)
kgschlosser wrote: Fri Apr 06, 2018 3:58 pm
the requests library has a convince method in the Response class..
Code: Select all
emby = requests.get(url, headers = headers)
films = emby.json()
But you still should always have some error handling any time you are dealing with data conversions. you could get something that is all mucked up
Code: Select all
try:
emby = requests.get(url, headers = headers)
films = emby.json()
except (requests.HTTPError, ValueError):
eg.StopMacro()
eg.Exit()
in the example above. the requests.HTTPError covers all exceptions generated from requests dealing with the HTTP connection. the ValueError covers the json data conversion in the event it fails. This will stop the current macro and exit the script. you can have it print some kind of information if you wanted informing you of the error.
Your example above replaced header declarations below, correct?
Code: Select all
headers = {
'content-type': 'application/json',
'Authorization': 'MediaBrowser',
'UserId': embyusr,
'Client': 'EmbyTrailers',
'Device': 'Python Script',
'DeviceId': 'xxx',
'Version': '1.0.0.0',
'X-MediaBrowser-Token': embykey,
Also, this script depends on an ini file for things like the api url, and key. Would I stick this file in a particular place, or should I attempt to hard code the values in the script itself? Sorry for all of the questions. If I can get this right I would like to make an Emby plugin for EG as a sort of learning experience.
Re: Importing python libraries to run script but which libraries?
Posted: Tue May 08, 2018 7:11 am
by kgschlosser
this is your whole script with the bits added that i was talking about
Code: Select all
import sys
import requests
import urllib
import json
import ConfigParser
import glob
import os
from pytube import YouTube
config = ConfigParser.RawConfigParser()
config.read('trailers.ini')
embyapi = ""
embykey = ""
embyusr = ""
h = 0
i = 0
j = 0
k = 0
if config.has_option('emby', 'api'):
embyapi = config.get('emby', 'api')
else:
embyerror = "No Emby URL in Config File.\n"
if config.has_option('emby', 'key'):
embykey = config.get('emby', 'key')
else:
embyerror += "No Emby API Key in Config File.\n"
if config.has_option('emby', 'usr'):
embyusr = config.get('emby', 'usr')
else:
embyerror += "No Emby User ID in Config File."
if config.has_option('emby', 'dirfrom'):
embydirf = config.get('emby', 'dirfrom')
else:
embydirf = ""
if config.has_option('emby', 'dirto'):
embydirt = config.get('emby', 'dirto')
else:
embydirt = ""
if len(embyapi) == 0 or len(embykey) == 0 or len(embyusr) == 0:
print(embyerror)
sys.exit()
if embyapi[-1] != "/":
embyapi += "/"
url = embyapi + "Users/%s/Items?IncludeItemTypes=Movie&Recursive=true&StartIndex=0&format=json&fields=RemoteTrailers,Path" % (
embyusr)
headers = {
'content-type': 'application/json',
'Authorization': 'MediaBrowser',
'UserId': embyusr,
'Client': 'EmbyTrailers',
'Device': 'Python Script',
'DeviceId': 'xxx',
'Version': '1.0.0.0',
'X-MediaBrowser-Token': embykey,
}
try:
emby = requests.get(url, headers=headers)
films = emby.json()
except (requests.HTTPError, ValueError):
eg.StopMacro()
eg.Exit()
if not 'Name' in films['Items'][0]:
print
print("No Films Found")
else:
for film in films['Items']:
if film['LocalTrailerCount'] == 0:
h += 1
fulpath = film['Path'].encode("utf-8")
if embydirf != "" and embydirt != "":
fulpath = fulpath.replace(embydirf, embydirt, 1)
fulpath = os.path.normpath(fulpath.replace('\\', os.sep))
basefil = os.path.basename(fulpath)
basedir = os.path.dirname(fulpath)
trail = os.path.splitext(basefil)[0]
if trail[-3:-1] == "CD":
trail = trail[:-4]
if basedir[-1] != os.sep:
basedir += os.sep
if len(glob.glob(r"%s%s%s" % (basedir, trail, "-trailer*"))) == 0:
download = True
i += 1
for trailer in film['RemoteTrailers']:
if download:
try:
yt = YouTube(trailer['Url'].encode("utf-8"))
yt.set_filename(trail + "-trailer")
video = yt.filter('mp4')[-1]
video.download(basedir)
except Exception, e:
print(trail + " - " + trailer['Url'].encode(
"utf-8") + " - " + str(e))
if len(glob.glob(
r"%s%s%s" % (basedir, trail, "-trailer*"))) > 0:
download = False
j += 1
if download:
k += 1
print("Emby thinks %s Films are Missing Trailers" % (h))
print("%s Films Actually Missing Trailers" % (i))
print("Downloaded %s Trailers" % (j))
print("Unable to Download %s Trailers" % (k))
Re: Importing python libraries to run script but which libraries?
Posted: Tue May 08, 2018 8:07 am
by kgschlosser
better yet.
Here is a code shortened version of what you had. well it has more lines but that is because of code formatting so it's easier to read.
if i remove the formatting it is down to 96 lines and that is with a bunch of added exception handling.
Code: Select all
import requests
import ConfigParser
import os
import traceback
from pytube import YouTube
emby_error = []
emby_config = [
'No Emby URL in Config File.',
'No Emby API Key in Config File.',
'No Emby User ID in Config File.',
None,
None
]
config_keys = [
'api',
'key',
'usr',
'dirfrom',
'dirto'
]
config = ConfigParser.RawConfigParser()
config.read('trailers.ini')
for i, key in enumerate(config_keys):
if config.has_option('emby', key):
emby_config[i] = config.get('emby', key)
elif emby_config[i] is not None:
emby_error += [emby_config[i]]
if emby_error:
eg.PrintError('\n'.join(emby_error))
eg.StopMacro()
eg.Exit()
(
emby_url,
emby_api_key,
emby_user,
emby_source_directory,
emby_destination_directory
) = emby_config
if not emby_url.endswith('/'):
emby_url += '/'
url = (
'{emby_url}Users/{emby_user}/Items?'
'IncludeItemTypes=Movie&'
'Recursive=true&'
'StartIndex=0&format=json&'
'fields=RemoteTrailers,Path'
).format(emby_url=emby_url, emby_user=emby_user)
headers = {
'content-type': 'application/json',
'Authorization': 'MediaBrowser',
'UserId': emby_user,
'Client': 'EmbyTrailers',
'Device': 'Python Script',
'DeviceId': 'xxx',
'Version': '1.0.0.0',
'X-MediaBrowser-Token': emby_api_key,
}
try:
response = requests.get(url, headers=headers)
films = response.json()
except (requests.HTTPError, ValueError):
traceback.print_exc()
eg.StopMacro()
eg.Exit()
else:
if 'Name' not in films['Items'][0]:
eg.PrintNotice("No Films Found")
eg.StopMacro()
eg.Exit()
questionable_trailers = 0
missing_trailers = 0
successful_trailer_downloads = 0
failed_trailer_downloads = 0
for film in films['Items']:
if film['LocalTrailerCount'] == 0:
questionable_trailers += 1
film_path = film['Path'].encode('utf-8')
if None not in (emby_source_directory, emby_destination_directory):
film_path = film_path.replace(
emby_source_directory,
emby_destination_directory,
1
)
film_path = os.path.normpath(film_path.replace('\\', os.sep))
film_base_path = os.path.basename(film_path)
film_directory_name = os.path.dirname(film_path)
film_name = os.path.splitext(film_base_path)[0]
if film_name[-3:-1] == 'CD':
film_name = film_name[:-4]
for f in os.listdir(film_directory_name):
if f.startswith(film_name + '-trailer'):
break
else:
missing_trailers += 1
for trailer in film['RemoteTrailers']:
trailer_url = trailer['Url'].encode('utf-8')
try:
you_tube = YouTube(trailer_url)
you_tube.set_filename(film_name + '-trailer')
video = you_tube.filter('mp4')[-1]
video.download(film_directory_name)
successful_trailer_downloads += 1
break
except:
eg.PrintError(
'{0} - {1}'.format(film_name, trailer_url)
)
traceback.print_exc()
else:
failed_trailer_downloads += 1
eg.Print(
'Emby thinks %d Films are Missing Trailers' % questionable_trailers
)
eg.Print('%d Films Actually Missing Trailers' % missing_trailers)
eg.Print('Downloaded %d Trailers' % successful_trailer_downloads)
eg.Print('Unable to Download %d Trailers' % failed_trailer_downloads)
Re: Importing python libraries to run script but which libraries?
Posted: Tue May 08, 2018 2:21 pm
by jachin99
What should I do with trailers.ini? Do I put this in the pytube library folder? Thanks for all of the help
Re: Importing python libraries to run script but which libraries?
Posted: Tue May 08, 2018 3:00 pm
by kgschlosser
idk I am just rewriting the script you gave me. i didn't change what it was doing or where it was grabbing data from. I simply changed how it was going about doing it.
I would assume that you put the ini file in the cwd (current working directory) which should be %appdata%/EvenGhost
I thought you were using the version of the script you posted earlier. this is a simplified version of that same script. I am assuming that you are running this from inside of EventGhost. I would imagine that you put this into a python script action and run it.
Re: Importing python libraries to run script but which libraries?
Posted: Tue May 08, 2018 3:07 pm
by kgschlosser
ok ok i see what is happening here...
LOL
I have never used Emby before. and i was misunderstanding hat you are trying to do.
Do you have an Emby account?
Have you installed the Python Youtube library into EventGhost?
Do you have an ini file written for Emby?
Re: Importing python libraries to run script but which libraries?
Posted: Tue May 08, 2018 3:49 pm
by jachin99
No Worries. I didn't create this script, it was something someone else did as a project, and appears to be abandoned. I have an emby account, and I have a local instance of emby server running on one of my machines. This emby server instance reads all of my media from a file server. i would assume that when I authenticate to the emby api, the script would work off of emby's authentication to my file server. I have already put in the web address, api key, and user information in my .ini file.
For pytube, I downloaded what i assume to be the correct version, and placed the pytube folder in my site-packages eg folder. There is no requirement for my personal use to even have an ini file but if this script runs off of one then I'm not sure where to put it. Thanks again.
Re: Importing python libraries to run script but which libraries?
Posted: Tue May 08, 2018 6:16 pm
by kgschlosser
I would poke about the Emby server for some means to output that ini file. The reason why i say this is that sometimes an API key may not be an actual API key. but instead it is an Auth Token. and Auth Tokens expire and need to be updated. That being stated the ini file contents specifically the key names seem like they are from someone that is new to programming. just like the script was as well. So it could be user created. I do not know...
We can forgo the ini file if you like. I don't see a use for it personally. it's simply one more thing to have to pay attention to and remember to backup.
here is the code with the ini file BS removed. directions are at the top.
Code: Select all
# you need to change these variable below to they proper values.
# the last 2 copy andpaste the directory right from file explorer
# and paste it between the single quotes.
# you have to leave the "r" in front.
emby_url = 'API URL'
emby_api_key = 'API KEY'
emby_user = 'SOME USER NAME'
emby_source_directory = r'SOURCE DIRECTORY'
emby_destination_directory = r'DESTINATION DIRECTORY'
import requests
import os
import traceback
from pytube import YouTube
url = (
'{emby_url}/Users/{emby_user}/Items?'
'IncludeItemTypes=Movie&'
'Recursive=true&'
'StartIndex=0&format=json&'
'fields=RemoteTrailers,Path'
).format(emby_url=emby_url, emby_user=emby_user)
headers = {
'content-type': 'application/json',
'Authorization': 'MediaBrowser',
'UserId': emby_user,
'Client': 'EmbyTrailers',
'Device': 'Python Script',
'DeviceId': 'xxx',
'Version': '1.0.0.0',
'X-MediaBrowser-Token': emby_api_key,
}
try:
response = requests.get(url, headers=headers)
films = response.json()
except (requests.HTTPError, ValueError):
traceback.print_exc()
eg.StopMacro()
eg.Exit()
else:
if 'Name' not in films['Items'][0]:
eg.PrintNotice("No Films Found")
eg.StopMacro()
eg.Exit()
questionable_trailers = 0
missing_trailers = 0
successful_trailer_downloads = 0
failed_trailer_downloads = 0
for film in films['Items']:
if film['LocalTrailerCount'] == 0:
questionable_trailers += 1
film_path = film['Path'].encode('utf-8')
if None not in (emby_source_directory, emby_destination_directory):
film_path = film_path.replace(
emby_source_directory,
emby_destination_directory,
1
)
film_path = os.path.normpath(film_path.replace('\\', os.sep))
film_base_path = os.path.basename(film_path)
film_directory_name = os.path.dirname(film_path)
film_name = os.path.splitext(film_base_path)[0]
if film_name[-3:-1] == 'CD':
film_name = film_name[:-4]
for f in os.listdir(film_directory_name):
if f.startswith(film_name + '-trailer'):
break
else:
missing_trailers += 1
for trailer in film['RemoteTrailers']:
trailer_url = trailer['Url'].encode('utf-8')
try:
you_tube = YouTube(trailer_url)
you_tube.set_filename(film_name + '-trailer')
video = you_tube.filter('mp4')[-1]
video.download(film_directory_name)
successful_trailer_downloads += 1
break
except:
eg.PrintError(
'{0} - {1}'.format(film_name, trailer_url)
)
traceback.print_exc()
else:
failed_trailer_downloads += 1
eg.Print(
'Emby thinks %d Films are Missing Trailers' % questionable_trailers
)
eg.Print('%d Films Actually Missing Trailers' % missing_trailers)
eg.Print('Downloaded %d Trailers' % successful_trailer_downloads)
eg.Print('Unable to Download %d Trailers' % failed_trailer_downloads)
Re: Importing python libraries to run script but which libraries?
Posted: Tue May 08, 2018 7:06 pm
by jachin99
I'll take a look at that, thanks. The API key is user generated, and I think its a lot like the pushbullet api keys. I don't know a lot about the specifics of how they work to be honest. I know you can share libraries with them.
Re: Importing python libraries to run script but which libraries?
Posted: Tue May 08, 2018 7:16 pm
by kgschlosser
ok so the API key will be static and will not change at all. so that can be directly entered into the script. as can the username. the only things would be the url which would be static as well. The directories all depend on what you want. So there is no real need for the ini file.
Re: Importing python libraries to run script but which libraries?
Posted: Tue May 08, 2018 8:26 pm
by jachin99
The author mentioned the director from and dir to values weren't relevant on windows but I'll see I guess. Emby knows where all of my files are and it detects trailers in a specific naming format and directory. If it doesn't work out I'll start chasing errors.