Can pip (or setuptools, distribute etc...) list the license used by each installed package?
Solution 1
You can use pkg_resources
:
import pkg_resources
def get_pkg_license(pkgname):
"""
Given a package reference (as from requirements.txt),
return license listed in package metadata.
NOTE: This function does no error checking and is for
demonstration purposes only.
"""
pkgs = pkg_resources.require(pkgname)
pkg = pkgs[0]
for line in pkg.get_metadata_lines('PKG-INFO'):
(k, v) = line.split(': ', 1)
if k == "License":
return v
return None
Example use:
>>> get_pkg_license('mercurial')
'GNU GPLv2+'
>>> get_pkg_license('pytz')
'MIT'
>>> get_pkg_license('django')
'UNKNOWN'
Solution 2
Here is a copy-pasteable snippet which will print your packages.
Requires: prettytable (pip install prettytable
)
Code
import pkg_resources
import prettytable
def get_pkg_license(pkg):
try:
lines = pkg.get_metadata_lines('METADATA')
except:
lines = pkg.get_metadata_lines('PKG-INFO')
for line in lines:
if line.startswith('License:'):
return line[9:]
return '(Licence not found)'
def print_packages_and_licenses():
t = prettytable.PrettyTable(['Package', 'License'])
for pkg in sorted(pkg_resources.working_set, key=lambda x: str(x).lower()):
t.add_row((str(pkg), get_pkg_license(pkg)))
print(t)
if __name__ == "__main__":
print_packages_and_licenses()
Example Output
+---------------------------+--------------------------------------------------------------+
| Package | License |
+---------------------------+--------------------------------------------------------------+
| appdirs 1.4.3 | MIT |
| argon2-cffi 16.3.0 | MIT |
| boto3 1.4.4 | Apache License 2.0 |
| botocore 1.5.21 | Apache License 2.0 |
| cffi 1.10.0 | MIT |
| colorama 0.3.9 | BSD |
| decorator 4.0.11 | new BSD License |
| Django 1.11 | BSD |
| django-debug-toolbar 1.7 | BSD |
| django-environ 0.4.3 | MIT License |
| django-storages 1.5.2 | BSD |
| django-uuslug 1.1.8 | BSD |
| djangorestframework 3.6.2 | BSD |
| docutils 0.13.1 | public domain, Python, 2-Clause BSD, GPL 3 (see COPYING.txt) |
| EasyProcess 0.2.3 | BSD |
| ipython 6.0.0 | BSD |
| ipython-genutils 0.2.0 | BSD |
| jedi 0.10.2 | MIT |
| jmespath 0.9.1 | MIT |
| packaging 16.8 | BSD or Apache License, Version 2.0 |
| pickleshare 0.7.4 | MIT |
| pip 9.0.1 | MIT |
| prettytable 0.7.2 | BSD (3 clause) |
| prompt-toolkit 1.0.14 | UNKNOWN |
| psycopg2 2.6.2 | LGPL with exceptions or ZPL |
| pycparser 2.17 | BSD |
| Pygments 2.2.0 | BSD License |
| pyparsing 2.2.0 | MIT License |
| python-dateutil 2.6.0 | Simplified BSD |
| python-slugify 1.2.4 | MIT |
| pytz 2017.2 | MIT |
| PyVirtualDisplay 0.2.1 | BSD |
| s3transfer 0.1.10 | Apache License 2.0 |
| selenium 3.0.2 | UNKNOWN |
| setuptools 35.0.2 | UNKNOWN |
| simplegeneric 0.8.1 | ZPL 2.1 |
| six 1.10.0 | MIT |
| sqlparse 0.2.3 | BSD |
| traitlets 4.3.2 | BSD |
| Unidecode 0.4.20 | GPL |
| wcwidth 0.1.7 | MIT |
| wheel 0.30.0a0 | MIT |
| win-unicode-console 0.5 | MIT |
+---------------------------+--------------------------------------------------------------+
Solution 3
Here is a way to do this with yolk3k (Command-line tool for querying PyPI and Python packages installed on your system.)
pip install yolk3k
yolk -l -f license
#-l lists all installed packages
#-f Show specific metadata fields (In this case, License)
Solution 4
1. Choice
pip-licenses PyPI package.
2. Relevance
This answer is relevant for March 2018. In the future, the data of this answer may be obsolete.
3. Argumentation
- simply installation —
pip install pip-licenses
, - more features and options, than yolk3k,
- active maintained.
4. Demonstration
Example output:
D:\KristinitaPelican>pipenv run pip-licenses --with-system --order=license --format-markdown
| Name | Version | License |
|---------------------|-----------|--------------------------------------------------------------|
| requests | 2.18.4 | Apache 2.0 |
| actdiag | 0.5.4 | Apache License 2.0 |
| blockdiag | 1.5.3 | Apache License 2.0 |
| nwdiag | 1.0.4 | Apache License 2.0 |
| seqdiag | 0.9.5 | Apache License 2.0 |
| Jinja2 | 2.10 | BSD |
| MarkupSafe | 1.0 | BSD |
| license-info | 0.8.7 | BSD |
| pip-review | 1.0 | BSD |
| pylicense | 1 | BSD |
| PTable | 0.9.2 | BSD (3 clause) |
| webcolors | 1.8.1 | BSD 3-Clause |
| Markdown | 2.6.11 | BSD License |
| Pygments | 2.2.0 | BSD License |
| yolk3k | 0.9 | BSD License |
| packaging | 17.1 | BSD or Apache License, Version 2.0 |
| idna | 2.6 | BSD-like |
| markdown-newtab | 0.2.0 | CC0 |
| pyembed | 1.3.3 | Copyright © 2013 Matt Thomson |
| pyembed-markdown | 1.1.0 | Copyright © 2013 Matt Thomson |
| python-dateutil | 2.7.2 | Dual License |
| Unidecode | 1.0.22 | GPL |
| chardet | 3.0.4 | LGPL |
| beautifulsoup4 | 4.6.0 | MIT |
| funcparserlib | 0.3.6 | MIT |
| gevent | 1.2.2 | MIT |
| markdown-blockdiag | 0.7.0 | MIT |
| pip | 9.0.1 | MIT |
| pkgtools | 0.7.3 | MIT |
| pytz | 2018.3 | MIT |
| six | 1.11.0 | MIT |
| urllib3 | 1.22 | MIT |
| wheel | 0.30.0 | MIT |
| blinker | 1.4 | MIT License |
| greenlet | 0.4.13 | MIT License |
| pip-licenses | 1.7.0 | MIT License |
| pymdown-extensions | 4.9.2 | MIT License |
| pyparsing | 2.2.0 | MIT License |
| certifi | 2018.1.18 | MPL-2.0 |
| markdown-downheader | 1.1.0 | Simplified BSD License |
| Pillow | 5.0.0 | Standard PIL License |
| feedgenerator | 1.9 | UNKNOWN |
| license-lister | 0.1.1 | UNKNOWN |
| md-environ | 0.1.0 | UNKNOWN |
| mdx-cite | 1.0 | UNKNOWN |
| mdx-customspanclass | 1.1.1 | UNKNOWN |
| pelican | 3.7.1 | UNKNOWN |
| setuptools | 38.5.1 | UNKNOWN |
| docutils | 0.14 | public domain, Python, 2-Clause BSD, GPL 3 (see COPYING.txt) |
5. External link
Solution 5
A slightly better version for those running jupyter - uses Anaconda defaults - no install needed
import pkg_resources
import pandas as pd
def get_pkg_license(pkg):
try:
lines = pkg.get_metadata_lines('METADATA')
except:
lines = pkg.get_metadata_lines('PKG-INFO')
for line in lines:
if line.startswith('License:'):
return line[9:]
return '(Licence not found)'
def print_packages_and_licenses():
table = []
for pkg in sorted(pkg_resources.working_set, key=lambda x: str(x).lower()):
table.append([str(pkg).split(' ',1)[0], str(pkg).split(' ',1)[1], get_pkg_license(pkg)])
df = pd.DataFrame(table, columns=['Package', 'Version', 'License'])
return df
print_packages_and_licenses()
Comments
-
Jacob Rigby almost 2 years
I'm trying to audit a Python project with a large number of dependencies and while I can manually look up each project's homepage/license terms, it seems like most OSS packages should already contain the license name and version in their metadata.
Unfortunately I can't find any options in pip or easy_install to list more than the package name and installed version (via pip freeze).
Does anyone have pointers to a tool to list license metadata for Python packages?