I'm working on an XBMC plugin which requires a few Python modules not available via a requires tag in addon.xml (they are not in the XBMC repository as far as I'm aware). The documentation for plugin development seems to indicate that you can do this by adding the module(s) to the resources/lib/ subdirectory of your plugin directory.
I've done this and when testing it in XBMC I get an import error trying to import this module because it cannot be found.
I've read the other question I found on SO regarding this topic entitled Importing a python module into XBMC for use within an addon but the proposed solution there, of adding the module directory to the path before importing, doesn't work for me either. I get the same import error.
In fact I don't think that answer is correct because os.getcwd() in XBMC does not return your plugin directory path when called from within your plugin; so concatenating the path it gives with /resources/lib as the answer suggests won't yield a valid path. I modified the example to use getAddonInfo to find the plugin path from an Addon object via the xbmcaddon module and added that to the path concatenated with /resources/lib but it still did not work.
Putting the modules into the root of the plugin directory also doesn't work. I haven't been able to find specific documentation about how to do this correctly beyond the initial tutorial saying that I should add it to the resources/lib subdirectory.
So does anyone know how to do this or have an example of this being done successfully in another XBMC plugin?
Figured out my mistake. I wasn't paying attention to the path I was adding. I was adding the addon profile directory to sys.path using getAddonInfo('profile') when I should have been using getAddonInfo('path')
For future reference, if you want to add a subdirectory of your addon to the path, this is what I did:
import xbmcaddon
import os
...
my_addon = xbmcaddon.Addon('plugin.video.my_plugin')
addon_dir = xbmc.translatePath( my_addon.getAddonInfo('path') )
sys.path.append(os.path.join( addon_dir, 'resources', 'lib' ) )
import <whatever modules you want>
I guess that's yet another lesson in paying close attention to the content of an error message.
Related
I have a custom cell magic which I need to load from a relative path. I can do so when the module directory is in the same place as the notebook. However, it doesn't work when I have a more complex directory structure.
It works if the directory structure is this:
test_custom_magic\
|-custom_magic_code\
|-__init__.py
|-etcetc.py
|-test_notebook.ipy
In this scenario, I just do a %reload_ext custom_magic_code and my code works.
However, now that I'm done writing and testing the code, I'm trying to use it in a more complex directory:
important_project\
|-notebooks\
|-do_something_important.ipy
|-do_something_else_important.ipy
|-custom_magic_code\
|-__init__.py
|-etcetc.py
In do_something_important.ipy, I can't just %reload_ext custom_magic_code. I get a ModuleNotFoundError.
If I try %reload_ext ../custom_magic_code (or some other nested directory level), I get this error:
TypeError: the 'package' argument is required to perform a relative import for '../custom_magic_code'
How can I solve this problem?
Please note that my custom magic code is good enough for me to run locally. I'm not quite ready to package it and install via pip/conda/nbextension just yet (and I'm trying to avoid learning that anyway, until I can get my current code working).
So I ended up using the following code to include relevant directory among the paths python checks to find libraries:
module_path = os.path.abspath(os.path.join('../..'))
if module_path not in sys.path:
sys.path.append(module_path)
Seems to work!
I'm having a little issue with my package directories. The structure is as follows:
package folder with modules
Databases
In the package folder I have a lot of .py files with functions that I use from everywhere (so on another drive as well). Some functions like "guess_countries" use databases located in a subfolder. I did that because I want to export my code to github (private repo).
Here is the issue:
My module Geo_guesser needs to look for this path (so a subfolder): "Databases/Geo/Countries/Countries (ZIP+Dump).sqlite3"
However upon importing from another folder the current directory gets appended and it becomes "Z:/Other_folder/Databases/Geo/Countries/Countries (ZIP+Dump).sqlite3" instead of "A:/My_package/Databases/Geo/Countries/Countries (ZIP+Dump).sqlite3" where the databases are.
I don't want to use absolute paths because everything is contained in the package folder and in the future I'd like to make it pip-installable or maybe share it with others and so the absolute path won't be the same obviously.
Other infos:
In the module Geo_guesser I've tried using: os.path.realpath, __file__ and sys.argv without success (I looked up many topics before posting this).
I used conda develop to be able to import my package's modules from anywhere
Tools:
Anaconda, Python 3.6 and Jupyter
Thanks in advance for the help :)!
Well nevermind I finally found a code that works for me sorry :( :
import os, sys, inspect
# realpath() will make your script run, even if you symlink it :)
cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]))
if cmd_folder not in sys.path:
sys.path.insert(0, cmd_folder)
Source: Import a module from a relative path
I am following the tutorial here:
http://www.prokopyshen.com/create-custom-zipline-data-bundle
and trying to set up a custom bundle to get price from custom, non US financial assets. I am stuck on the line that says:
Advise zipline of our bundle by registering it via .zipline/extension.py
My extension.py file is located in the .zipline/ directiory and has the following code:
from zipline.data.bundles import register
from zipline.data.bundles.viacsv import viacsv
eqSym = {
"CBA"
}
register(
'CBA.csv', # name this whatever you like
viacsv(eqSym),
)
I don't get what it means to register the bundle via .zipline/extension.py though? I thought it might mean to just run the extension.py file from my terminal via a:
python extenion.py
but that fails and says:
ImportError: No module named viacsv
How do i register this bundle?
I also followed this tutorial and I must confess this part is a little confusing.
First of all, I don't think it's necessary to run:
$ python extension.py
The error message you get probably comes from the fact that Python cannot find the viacsv.py file in sys.path (the places where it looks for modules, etc.). In the tutorial you mentioned, it's not really clear what to do with this file. As far as I am concerned, I just saved the viacsv.py file in my local site-packages directory. As I am on Linux I put it there ~/.local/lib/python2.7/site-packages but it might different for you. You can run the following python script to find out:
import sys
for dr in sys.path:
print dr
Then I just substituted from zipline.data.bundles.viacsv import viacsv with from viacsv import viacsv in extension.py.
I suspect you might be looking for the wrong place for the extension.py file.
For windows machine, the file is under "~\.zipline\extension.py". In my case, it's under "C:\Users\XXXX\.zipline\extension.py".
I had been looking at zipline folder under conda's site-packages folder, and couldn't find it. Then created an extension.py myself wondering why it's not called.
Check a related post here https://www.quantopian.com/posts/zipline-issue-while-creating-custom-bundle-to-bring-yahoo-data.
Same issue here, #Gillu13 pointed me to this solution.
I installed zipline through conda. So zipline is installed in
home/me/anaconda3/envs/krakenex/lib/python3.6/site-packages
in there you will find zipline/data/bundles and you can put viacsv.py in there...
then
from zipline.data.bundles.viacsv import viacsv
works
I'm trying to deploy a Flask app on GAE using Windows. It runs fine locally but runs into problems when I try to run it on GAE.
First I get this error in flask\json.py:
from itsdangerous import json as _json
ImportError: No module named itsdangerous
Downloading and unpacking https://pypi.python.org/pypi/itsdangerous in the same directory doesn't fix the issue. If I just grab itsdangerous.py and put it in the flask directory, I get:
_slash_escape = '\\/' not in _json.dumps('/')
AttributeError: 'module' object has no attribute 'dumps'
I've read that it may be due to conflicting json.py files but I've also tried using absolute paths for the import json and it doesn't seem to make a difference.
You put the itsdangerous.py in the wrong directory. Because json.py and itsdangerous.py both exist in the /flask directory, itsdangerous.py will import /flask/json.py intead of the right one.
The GAE official doc mentioned a way to include 3rd-party libraries:
You can include other pure Python libraries with your application by
putting the code in your application directory. If you make a symbolic
link to a module's directory in your application directory, appcfg.py
will follow the link and include the module in your app.
Obviously, it's a poor solution because we don't want to mix the libraries we used with the code we write. The community have found better ways.
I suggest you to use a gae-flask project template(e.g. flask-appengine-template) or at least follow some of its project structure. You can put all these 3rd-party libraries under a directory like /lib and add '/lib' to sys.path. Actually flask-appengine-template include common flask modules like itsdangerous for you by default.
sample code:
import os
import sys
sys.path.insert(1, os.path.join(os.path.abspath('.'), 'lib'))
import application
Google now makes it super-easy:
https://console.developers.google.com/start/appengine
The latest Python2.7 has a google directory within dist-packages, making it impossible to import the google directory which contains appengine and other packages from another location. Such directory is required to work to effect imports from GoogleAppEngine (GAE) code on the dev_server. Otherwise such imports fail. An example of such import is:
from google.appengine.api import mail
which yields
ImportError: No module named appengine.api
This issue is similar to the one in here and indeed following Alex Martelli's reply the location of my google import is
In [1]: import google
In [2]: google.__file__
Out[2]: '/usr/lib/python2.7/dist-packages/google/__init__.pyc'
rather than the one where I placed the GAE unzipped files.
Any recommended way to fix this? I already thought about dirty hacks to fix this, such as putting soft links in the dist-packages google directory, but again, that's dirty.
Packages have a special attribute, __path__, which tells the Python interpreter where to look for modules and subpackages. By modifying this, you can let Python find contents from both google directories. Using the pkgutil module, this ought to work (untested):
import pkgutil
import google
google.__path__ = pkgutil.extend_path(google.__path__, google.__name__)
Are you sure this google directory came with Python 2.7? I've seen it too, but it appeared for the first time when I installed some utility from Google (I think it was Google Storage for Developers). I also think there's a .pth file related to this.