py2app error running app
Asked Answered
I

3

3

macOS 10.12

I'm trying to package a python script (called getUrls_douyu.py) as a standalone application/executable without dependencies, so I'm using py2app. The problem is that when I try to run my app after building (from terminal with: open getUrls_douyu.app), nothing happens and I get the following error prompt:

image of error prompt

The console error:

Detected missing constraints for <private>.  It cannot be placed because there are not enough constraints to fully define the size and origin. Add the missing constraints, or set translatesAutoresizingMaskIntoConstraints=YES and constraints will be generated for you. If this view is laid out manually on macOS 10.12 and later, you may choose to not call [super layout] from your override. Set a breakpoint on DETECTED_MISSING_CONSTRAINTS to debug. This error will only be logged once.

If I try open getUrls_douyu.app/Contents/MacOS/getUrls_douyu (the executable inside the app bundle), I get a different error:

IOError: Could not find a suitable TLS CA certificate bundle, invalid path: /Users/<REDACTED>/getUrls_douyu/dist/getUrls_douyu.app/Contents/Resources/lib/python2.7/site-packages.zip/certifi/cacert.pem

But I checked and cacert.pem does indeed exist there, so for some reason the certificate is invalid? My .py script uses requests module to get stuff from a webpage which I think must be the issue. Here's my full python script:

import requests
from bs4 import BeautifulSoup

html = requests.get('https://www.douyu.com/directory/all').text
soup = BeautifulSoup(html, 'html.parser')
urls = soup.select('.play-list-link')

output = '';
output += '[' #open json array
for i, url in enumerate(urls):
    channelName = str(i);
    channelUrl = 'http://douyu.com' + url.get('href')
    output += '{'
    output += '\"channelName\":' + '\"' + channelName.encode('utf-8') + '\",'
    output += '\"channelUrl\":' + '\"' + channelUrl.encode('utf-8') + '\"'
    output += '},'

output = output[:-1]
output += ']'

print output

When I first built this script I did so in a virtualenv within which I've done pip install requests and pip install beautifulsoup4 and tested that the script successfully ran with no problem.

This answer to a question regarding the cacert.pem error with the requests module did not help me. Here is my python script when applying that given solution:

import requests
from bs4 import BeautifulSoup
import sys, os

def override_where():
    """ overrides certifi.core.where to return actual location of cacert.pem"""
    # change this to match the location of cacert.pem
    return os.path.abspath("cacert.pem")


# is the program compiled?
if hasattr(sys, "frozen"):
    import certifi.core

    os.environ["REQUESTS_CA_BUNDLE"] = override_where()
    certifi.core.where = override_where

    # delay importing until after where() has been replaced
    import requests.utils
    import requests.adapters
    # replace these variables in case these modules were
    # imported before we replaced certifi.core.where
    requests.utils.DEFAULT_CA_BUNDLE_PATH = override_where()
    requests.adapters.DEFAULT_CA_BUNDLE_PATH = override_where()

html = requests.get('https://www.douyu.com/directory/all').text
soup = BeautifulSoup(html, 'html.parser')
urls = soup.select('.play-list-link')

output = '';
output += '[' #open json array
for i, url in enumerate(urls):
    channelName = str(i);
    channelUrl = 'http://douyu.com' + url.get('href')
    output += '{'
    output += '\"channelName\":' + '\"' + channelName.encode('utf-8') + '\",'
    output += '\"channelUrl\":' + '\"' + channelUrl.encode('utf-8') + '\"'
    output += '},'

output = output[:-1]
output += ']'

print output

I think I've set up my py2app setup.py file correctly...

from setuptools import setup

APP = ['getUrls_douyu.py']
DATA_FILES = []
OPTIONS = {}

setup(
    app=APP,
    data_files=DATA_FILES,
    options={'py2app': OPTIONS},
    setup_requires=['py2app'],
)

Sorry for the verbose question! I'm new-ish to python so I imagine I've made some dumb mistake. Any help GREATLY appreciated.

Interlocution answered 29/4, 2018 at 20:46 Comment(0)
C
2

Try updating py2app options to:

OPTIONS = {
    'packages': ['certifi',]
}

This way you're explicitly letting py2app include certifi package.

If you look at .pem file it's trying to find:

../site-packages.zip/certifi/cacert.pem

It won't be able to find any file in .zip since it's not a folder.

Another tip/trick is to run your app by opening

dist/App.app/Contents/MacOS/App

This will open up a terminal with logs which help you debug the issue easier.

Crossbreed answered 17/5, 2018 at 15:17 Comment(0)
U
0

A quick workaround: "python setup.py py2app --packages=wx",

from the author https://bitbucket.org/ronaldoussoren/py2app/issues/252/py2app-creates-broken-bundles-with

Unprintable answered 21/12, 2019 at 21:44 Comment(0)
C
-1

You have to add 'cifi' in the packages in order for it to run

from setuptools import setup
APP = ['']  # file name
DATA_FILES = []

OPTIONS = {

   'iconfile': '', # icon
   'argv_emulation': True,
   'packages': ['certifi', 'cffi'], # you need to add cffi
}

 setup(

      app=APP,
      data_files=DATA_FILES,
      options={'py2app': OPTIONS},
      setup_requires=['py2app'],
   )
Connatural answered 1/3, 2022 at 5:8 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Deadline

© 2022 - 2024 — McMap. All rights reserved.