I have been trying to make a standalone app using py2app using this tutorial but instead of using the forked version I used the official version.. Using python setup.py py2app -A
worked fine but when using python setup.py py2app
it gave an error. The last line was ImportError: No module named 'google-api-python-client'
(full output can be found here.).
Things I have tried
python3 setup.py py2app
I have also looked at this stackoverflow article but it gave the same error.
Setup.py
from setuptools import setup
APP = ['YoutubeSubCount.py']
DATA_FILES = ['key.txt', 'logo_sub.png', 'logo_sub2.icns']
APP_NAME = "Youtube Sub Count"
OPTIONS = {
'argv_emulation': True,
'iconfile': 'icon.icns',
'plist': {
'CFBundleName': APP_NAME,
'CFBundleDisplayName': APP_NAME,
'CFBundleVersion': "0.1.0",
'CFBundleShortVersionString': "0.1.0",
'LSUIElement': True,
},
'packages': ['rumps', 'sty', 'google-api-python-client'],
}
setup(
app=APP,
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
)
YoutubeSubCount.py
import rumps
import time
import sys
import os
import linecache
from tkinter import *
from sty import fg
from googleapiclient.discovery import build
global update_timer, key, service, channel
key = open(os.path.join(sys.path[0], './key.txt')).read().strip()
service = build('youtube', 'v3', developerKey=key)
channel2 = 'UCERizKQbgpBXOck0R6t_--Q'
subs = service.channels().list(
part='statistics',
id= channel2
).execute()['items'][0]['statistics']['subscriberCount']
timers = ["1 secs","5 secs","10 secs","15 secs","20 secs","25 secs","30 secs","35 secs","45 secs","50 secs","1 Min"]
update_timer = 60
key_path = "key.txt"
class Sub_Counter(rumps.App):
@rumps.timer(update_timer)
def pull_data(self, _):
subs = service.channels().list(
part='statistics',
id=channel2
).execute()['items'][0]['statistics']['subscriberCount']
a = (str(subs))
self.icon = "logo_sub.png"
self.title = "Subscribers: " + str(a)
self.notification = str(a) + " Subscribers"
@rumps.clicked('About')
def about(self, _):
rumps.notification("Youtube Subscriber Count", "Made by Roxiun using Python & rumps", "Shows Youtube Subscriber counts")
@rumps.clicked('Preferences', 'API Key')
def configuration_window_api(self, _):
response = rumps.Window('Enter new API Key')
response.dimensions=(320, 160)
response.run()
if response.clicked:
key = response.text
service = build('youtube', 'v3', developerKey=key)
@rumps.clicked('Preferences', 'Channel')
def configuration_window_channel(self, _):
response = rumps.Window('Enter new Youtube Channel Link')
response.dimensions=(320, 160)
response.run()
if response.clicked:
channel = response.text
if "https://www.youtube.com/channel/" in channel:
channel2 = channel.replace("https://www.youtube.com/channel/", "")
else:
channel2 = channel.replace("https://www.youtube.com/user/", "")
subs = service.channels().list(
part='statistics',
id=channel2
).execute()['items'][0]['statistics']['subscriberCount']
a = (str(subs))
self.icon = "logo_sub.png"
self.title = "Subscribers: " + str(a)
self.notification = str(a) + " Subscribers"
@rumps.clicked('Icon', 'Normal')
def icon_on(self, _):
self.icon = 'logo_sub.png'
@rumps.clicked('Icon', 'Coloured')
def icon_col(self, _):
self.icon = 'logo_sub2.icns'
@rumps.clicked('Icon', 'Off')
def icon_off(self, _):
self.icon = None
@rumps.clicked('Update Timer', 'Every Second')
def timer_1(self, _):
update_timer = 1
@rumps.clicked('Update Timer', '5 Seconds')
def timer_2(self, _):
update_timer = 5
@rumps.clicked('Update Timer', '10 Seconds')
def timer_3(self, _):
update_timer = 10
@rumps.clicked('Update Timer', '20 Seconds')
def timer_4(self, _):
update_timer = 20
@rumps.clicked('Update Timer', '30 Seconds')
def timer_5(self, _):
update_timer = 30
@rumps.clicked('Update Timer', '40 Seconds')
def timer_6(self, _):
update_timer = 40
@rumps.clicked('Update Timer', '50 Seconds')
def timer_7(self, _):
update_timer = 50
@rumps.clicked('Update Timer', '1 Minute')
def timer_8(self, _):
update_timer = 60
@rumps.clicked("Detailed Statistics")
def Detailed_Statistics(self, _):
rumps.notification("You have:", self.notification , "Veiws Comming Soon")
app = Sub_Counter("Loading...")#debug=True
app.menu = [
('About'),
('Preferences',('API Key', 'Channel')),
None,
('Icon', ('Normal', 'Coloured', 'Off')),
('Update Timer', ('Every Second', '5 Seconds', '10 Seconds', '20 Seconds', '30 Seconds', '40 Seconds', '50 Seconds', '1 Minute')),
None,
("Detailed Statistics")
]
app.run()
Thanks in advance!
Update
After following the answer by Sergio Pulgarin
New Setup.py
from setuptools import setup
APP = ['YoutubeSubCount.py']
DATA_FILES = ['key.txt', 'logo_sub.png', 'logo_sub2.icns']
APP_NAME = "Youtube Sub Count"
OPTIONS = {
'argv_emulation': True,
'iconfile': 'icon.icns',
'plist': {
'CFBundleName': APP_NAME,
'CFBundleDisplayName': APP_NAME,
'CFBundleVersion': "0.1.0",
'CFBundleShortVersionString': "0.1.0",
'LSUIElement': True,
},
'packages': ['rumps', 'sty'],
}
setup(
app=APP,
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
install_requires=['google-api-python-client'],
)
Running python setup.py py2app -A
gave the expected output and worked fine but after running python setup.py py2app
no terminal output was given and the application was created, but upon open the application it opened a window sayinf Youtube Sub Count Error
and had a button saying Console and one saying Terminate
I know this is an old question but an easy workaround is to copy the google_api_python_client-*.dist-info in your respective Library/Frameworks/Python.framework/Versions/your_version/lib/python_version/site-packages/
folder and paste it inside the app_name.app/contents/Resources/lib/your_python_version/
folder.
After doing that, try running the app again from the terminal or clicking the file at app_name.app/contents/macOS/app_name as the first time you run it, it might be required to authenticate it with your gmail.
I hope this helps people with this problem in the future as I had.