I found myself regularly wanting to copy modules I had already written into new projects. Things like Dice classes, confirmation views, or even a reusable color picker view. I wasn't about to put everything I thought was useful or reusable in the site-packages. I was aware, however, of the ability to add a directory to the sys.path so I could reference and import it, but in an app on iOS, this full path is very long and gross, and trying to use relative paths instead was almost equally undesirable. And what if the module I made gets renamed or moved? Now all those hard-coded references to its path in other modules need to be found and updated.
I wrote this little helper module sharedlibs.py to simplify the process and dropped it in the site-packages folder.
'''
example use of this module:
import sharedlibs
sharedlibs.add_path_for('animated_image_view')
from animated_image_view import AnimatedImageView
'''
import os
import sys
def get_app_root():
# Returns the fully-qualified "root" directory of the Pythonista 3 app
end = 'Pythonista3/Documents'
cwd = os.getcwd()
return cwd.split(end)[0] + end
def add_path_for(*modules):
# Adds the directory for the given library name to the search path so its contents can be imported.
_libs = _load_libs_dict()
for module in modules:
if module in _libs:
sys.path.append(get_app_root() + _libs[module])
else:
raise Exception('No such shared module: .%s' % module)
# Prints a list of accessible libraries
def list():
_libs = _load_libs_dict()
print('Available Shared Libraries:')
for key in _libs:
print(' %s: %s' % (key, _libs[key]))
def _load_libs_dict():
d = {}
print(__file__)
libs_path = '%s/sharedlibs_list.txt' % '/'.join(__file__.split('/')[:-1])
with open(libs_path) as f:
lines = [l.strip() for l in f.readlines()]
for line in lines:
if line != '' and not line.startswith('#'):
k,v = line.split('=')
d[k] = v
return d
if __name__ == '__main__':
# just print the available libraries
list()
This module and a sharedlibs_list.txt file were both added to the site-packages and nothing else ever again.
The sharedlibs_list.txt is simply a key-value pair file containing the short names of the libraries mapped to their paths relative to the Pythonista's app root. Something like this:
animated_image_view=/UI/Views/AnimatedImageView
brightness=/Utils/ColorBrightness
config_file=/Utils/ConfigFile
img_utils=/Utils/ImageUtils
perm_utils=/Utils/PermutationUtils
ui_drag=/UI/Draggable
view_swap=/UI/ViewSwap
word_utils=/Utils/WordUtils
You'll notice you don't need the full path from your iOS device's actual root; the sharedlibs module treats the Pythonista3/Documents directory as your root since you can't really access much outside there anyway.
Once Pythonista is restarted, the listed libraries will be accessible via the sharedlibs.add_path_for() function, which will add that library's directory to the search path.
One single, clean place to define the locations of your reusable libraries for easy import anywhere.