Including a Python Library (suds) in a portable way - python

I'm using suds (brilliant library, btw), and I'd like to make it portable (so that everyone who uses the code that relies on it, can just checkout the files and run it).
I have tracked down 'suds-0.4-py2.6.egg' (in python/lib/site-packages), and put it in with my files, and I've tried:
import path.to.egg.file.suds
from path.to.egg.file.suds import *
import path.to.egg.file.suds-0.4-py2.6
The first two complain that suds doesn't exist, and the last one has invalid syntax.
In the __init__.py file, I have:
__all__ = [ "FileOne" ,
"FileTwo",
"suds-0.4-py2.6"]
and have previously tried
__all__ = [ "FileOne" ,
"FileTwo",
"suds"]
but neither work.
Is this the right way of going about it? If so, how can I get my imports to work. If not, how else can I achieve the same result?
Thanks

You must add your egg file to sys.path, like this:
import sys
# insert at 0 instead of appending to end to take precedence
# over system-installed suds (if there is one).
sys.path.insert(0, "suds-0.4-py2.6.egg")
import suds

.egg files are zipped archives; hence you cannot directly import them as you have discovered.
The easy way is to simply unzip the archive, and then copy the suds directory to your application's source code directory. Since Python will stop at the first module it discovers; your local copy of suds will be used even if it is not installed globally for Python.
One step up from that, is to add the egg to your path by appending it to sys.path.
However, the proper way would be to package your application for distribution; or provide a requirements file that lets other people know what external packages your program depends on.

Usually I distribute my program with a requirements.txt file that contain all dependencies and their version.
The users can then install these libraries with:
pip install -r requirements.txt
I don't think including eggs with your code is a good idea, what if the user use python2.7 instead of python2.6
More info about requirement file: http://www.pip-installer.org/en/latest/requirements.html

Related

How to simply call a PYD from a wheel installed package?

I'm building a pyd file via pybind11. There's no python-only code in the project (not even in the final wheel). I'm packing this prebuilt pyd into a wheel package. It's all working well so far, but I've got one small issue. Every time I want to use the functions from the pyd file (which is actually the primary "source" of code) I have to type the following: from python_lib_name.pyd_name import pyd_exported_class example: from crusher.crusher import Shard. This looks pretty lame, is there any way to prevent this and let the developer simply use the from crusher import Shard syntax?
Also, I'm not sure what information to provide, obviously, I wouldn't like to throw the whole project at you unnecessarily. I'm glad to provide any details by editing.
how about this: put your pyd in a folder and include a __init__.py that import the stuff from the pyd
my_project
|---my_pyd_lib
| |---my_pyd_lib.pyd
| |---__init__.py
|---#the other stuff
and in that init just put
#__init__.py
from .my_pyd_lib import *
the dot in the import make it a relative import useful to make sure that import the thing in the same folder as that file, it also make sure you import your thing if it happens to share a name with some other package/module you happens to have installed
One way to make a pyd file simply importable is to use the Python interpreter's -m flag. For example, if your file is called foo.pyd and is located in the current directory, you can import it by running the following command:
python -m foo
This will cause the Python interpreter to load the module from foo.pyd and then execute its contents as if they were written in a normal .py file. You can also use this technique to import modules that are located in different directories; just specify the path to the module as an argument to -m.
Another way to make a pyd file simply importable is to convert it into a normal .py file.

Pycharm venv packages not available to me?

I just created a pycharm virtual enviorment, and would like to use some specific packages inside of it. It's these two cryptography ones:
But when I try to import them in my code, the import doesnt complain, but when I try to acces the library, no suggestions are given.
What should I do in order to actually use a library?
I'm not familiar with crypto, but its top-level __init__.py contains nothing and hence there is nothing to suggest.
You'll receive completion with non-empty modules, e.g.:
import crypto.library.hash
crypto.library.hash.<here>
# or
from crypto.library import hash
hash.<here>

How should I set up the python packages for this

I am creating a tool I plan to put on Github. It is very general however I want to also include some examples of its usage. As such I have set up the following folder structure.
This tool is for python 3.
repository/
commonTool.py
commonTool2.py
specificUsage/
runTheSpecificUsage.py
helpRunTheSpecificUsage.py
Now both of the scripts in the specificUsage/ folder will import the methods in commonTool.py and commonTool2.py.
My issue is ideally the user would be able to go
python repository/specificUsage/runTheSpecificUsage.py
However I cant get this to work. It never is able to import the functions that are in the folder above it. I have tried a variety of various posts on how to import a file from a super folder with no luck.
How should I be setting up these folders? Should I have one init.py or two? Where?
You can create a setup.py at the top level along with commonTool.py and commonTool2.py. Inside your setup.py, put the following line:
import setuptools
setuptools.setup(packages=setuptools.find_packages())
Then put an __init__.py in the same level, as well as in specificUsage/. You should be able to import from specificUsage like this:
import commonTool
After setting up your files, from the top level run:
pip install -e .
You may also want to consider that Python has strong naming conventions for modules and packages and frowns upon camelcase in general. You can read more here if you like.

What is the cleanest way to add a directory of third-party packages to the beginning of the Python path?

My context is appengine_config.py, but this is really a general Python question.
Given that we've cloned a repo of an app that has an empty directory lib in it, and that we populate lib with packages by using the command pip install -r requirements.txt --target lib, then:
dirname ='lib'
dirpath = os.path.join(os.path.dirname(__file__), dirname)
For importing purposes, we can add such a filesystem path to the beginning of the Python path in the following way (we use index 1 because the first position should remain '.', the current directory):
sys.path.insert(1, dirpath)
However, that won't work if any of the packages in that directory are namespace packages.
To support namespace packages we can instead use:
site.addsitedir(dirpath)
But that appends the new directory to the end of the path, which we don't want in case we need to override a platform-supplied package (such as WebOb) with a newer version.
The solution I have so far is this bit of code which I'd really like to simplify:
sys.path, remainder = sys.path[:1], sys.path[1:]
site.addsitedir(dirpath)
sys.path.extend(remainder)
Is there a cleaner or more Pythonic way of accomplishing this?
For this answer I assume you know how to use setuptools and setup.py.
Assuming you would like to use the standard setuptools workflow for development, I recommend using this code snipped in your appengine_config.py:
import os
import sys
if os.environ.get('CURRENT_VERSION_ID') == 'testbed-version':
# If we are unittesting, fake the non-existence of appengine_config.
# The error message of the import error is handled by gae and must
# exactly match the proper string.
raise ImportError('No module named appengine_config')
# Imports are done relative because Google app engine prohibits
# absolute imports.
lib_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'libs')
# Add every library to sys.path.
if os.path.isdir(lib_dir):
for lib in os.listdir(lib_dir):
if lib.endswith('.egg'):
lib = os.path.join(lib_dir, lib)
# Insert to override default libraries such as webob 1.1.1.
sys.path.insert(0, lib)
And this piece of code in setup.cfg:
[develop]
install-dir = libs
always-copy = true
If you type python setup.py develop, the libraries are downloaded as eggs in the libs directory. appengine_config inserts them to your path.
We use this at work to include webob==1.3.1 and internal packages which are all namespaced using our company namespace.
You may want to have a look at the answers in the Stack Overflow thread, "How do I manage third-party Python libraries with Google App Engine? (virtualenv? pip?)," but for your particular predicament with namespace packages, you're running up against a long-standing issue I filed against site.addsitedir's behavior of appending to sys.path instead of inserting after the first element. Please feel free to add to that discussion with a link to this use case.
I do want to address something else that you said that I think is misleading:
My context is appengine_config.py, but this is really a general Python
question.
The question actually arises from the limitations of Google App Engine and the inability to install third-party packages, and hence, seeking a workaround. Rather than manually adjusting sys.path and using site.addsitedir. In general Python development, if your code uses these, you're Doing It Wrong.
The Python Packaging Authority (PyPA) describes the best practices to put third party libraries on your path, which I outline below:
Create a virtualenv
Mark out your dependencies in your setup.py and/or requirements files (see PyPA's "Concepts and Analyses")
Install your dependencies into the virtualenv with pip
Install your project, itself, into the virtualenv with pip and the -e/--editable flag.
Unfortunately, Google App Engine is incompatible with virtualenv and with pip. GAE chose to block this toolset in an attempt sandbox the environment. Hence, one must use hacks to work around the limitations of GAE to use additional or newer third party libraries.
If you dislike this limitation and want to use standard Python tooling for managing third-party package dependencies, other Platform as a Service providers out there eagerly await your business.

Getting Python to use the ActiveTcl libraries

Is there any way to get Python to use my ActiveTcl installation instead of having to copy the ActiveTcl libraries into the Python/tcl directory?
Not familiar with ActiveTcl, but in general here is how to get a package/module to be loaded when that name already exists in the standard library:
import sys
dir_name="/usr/lib/mydir"
sys.path.insert(0,dir_name)
Substitute the value for dir_name with the path to the directory containing your package/module, and run the above code before anything is imported. This is often done through a 'sitecustomize.py' file so that it will take effect as soon as the interpreter starts up so you won't need to worry about import ordering.

Categories