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.

A__
  • 1,616
  • 2
  • 19
  • 33

3 Answers3

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.

Nam Ngo
  • 2,093
  • 1
  • 23
  • 30
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

Fan Yer
  • 377
  • 3
  • 7
-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'],
   )
ilham
  • 1
  • 2
  • 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](/help/how-to-answer). – Community Mar 01 '22 at 09:01