问题
I have an python application that uses the Python Imaging Library (PIL) and is packaged using Py2app. Numpy dylibs are found in the app contents directory:
demo.app/Contents/Resources/lib/python3.8/numpy/.dylibs/libgcc_s.1.dylib
where they can be searched for and signed but PIP dylibs are inside a python3.8.zip
file
demo.app/Contents/Resources/lib/python3.zip -> ./PIL/.dylibs/libfreetype.6.dylib
where one would have to unzip, sign, and rezip them. Why does this happen and how do I prevent it so that I don't have to treat it different?
回答1:
py2app
implements special handling of certain packages via a mechanism called "recipes". It comes with built-in recipes for certain packages including numpy
, which is why numpy is excluded from the .zip
file. (Here's the built-in numpy recipe.)
In addition to the built-in recipes, you can define your own recipes for py2app to use. Just define a class that has a check
method, and monkey-patch it as an attribute onto py2app.recipes
:
# In setup.py
class PIL_recipe:
def check(self, cmd, mf):
m = mf.findNode("PIL")
if m is None or m.filename is None:
return None
# Exclude from site-packages.zip
return {"packages": ["PIL"]}
py2app.recipes.PIL = PIL_recipe()
...
setup(...)
If you need to do this with several libraries, you can generalize this trick so that it doesn't hard-code the name of the package:
class ExcludeFromZip_Recipe(object):
def __init__(self, module):
self.module = module
def check(self, cmd, mf):
m = mf.findNode(self.module)
if m is None:
return None
# Don't put the module in the site-packages.zip file
return {"packages": [self.module]}
for module in ['PIL', 'skimage', 'sklearn', 'jsonschema']:
setattr( py2app.recipes, module, ExcludeFromZip_Recipe(module) )
Disclaimer: This is how I've solved this problem in the past. But I'm not sure why your zip file is named python3.zip
instead of site-packages.zip
.
来源:https://stackoverflow.com/questions/62141863/py2app-placing-pil-dylibs-in-zip-file