I'm using buildozer to convert a python program to a phone app on Mac connected to an Android phone with the command line:
buildozer android debug deploy run
The previous command line runs the converted app on the connected phone.But the app crashes as soon as playsound is used. As for the methods before playsound work just fine.
When I run:
adb logcat | grep python
I get the error:
ImportError: dlopen failed: "/data/data/org.test.myapp/files/app/_python_bundle/site-packages/gi/_gi.so" has bad ELF magic
When I looked it up I found that Mac cannot use .so files.
Does anybody know how I can solve this?
Okay, so I ended up fixing this when I got a similar error. (dawg.so has bad ELF magic)
Basically, the reason I got this error was because the library ("gi" in your case) was not been read properly by the android phone when deployed and hence, was "corrupted".
The bottomline reason (for me) was that it was a C/C++ library under the hood and used Cython to be converted to a Python library. Hence, this error usually means that your library needs a custom recipe.
Steps to solve it:
In the root directory (where .buildozer folder is found), I added a folder named dawg (the library name), and then, inside dawg, I git cloned the source files of dawg. To get the source files, you can just go to the PyPi page for that library and go to the Project links -> Homepage of their GitHub site. Once cloned, you can also remove .git, .gitignore, from the source files.
Once that's done, run python3 setup.py install in the dawg directory to install and hence, "cythonize" the source files
In .buildozer/android/platform/python-for android/pythonforandroid/recipes, add a new folder named "dawg" (your library name) and then, inside /dawg, make _init_.py where you will add your custom recipe.
In _init_.py, you can add your recipe and the path to the source files. Here is a template that worked for me, but you can customize it for you as per your requirements.
from pythonforandroid.recipe import IncludedFilesBehaviour, CppCompiledComponentsPythonRecipe
import os
import sys
class DAWGRecipe(IncludedFilesBehaviour, CppCompiledComponentsPythonRecipe):
version = '0.8.0'
src_filename = "../../../../../../../dawg"
name = 'dawg'
# Libraries it depends on
depends = ['setuptools']
call_hostpython_via_targetpython = False
install_in_hostpython = True
def get_recipe_env(self, arch):
env = super().get_recipe_env(arch)
env['LDFLAGS'] += ' -lc++_shared'
return env
recipe = DAWGRecipe()
Don't forget to alter the buildozer.spec. To its p4a.local_recipes, add the local path to /.buildozer/android/platform/python-for-android/pythonforandroid/recipes as that's where we add our recipes.
Clean the previous build by running buildozer android clean
Lastly, run buildozer -v android debug deploy run to build the app on android phone again.
Hope this helps :)
Related
I am using kivy to create an android app. I need to install the deepspeech framework, however, in order for deepspeech to be installed it is necessary to create a recipe.
I created a recipe and built the apk, there were no errors in the build, it created the apk and also, as far as I could see in the folders, the deepspeech was built. However after I install the app in the phone and try to run the app, it crashes and says there is no module named deepspeech.
Does anyone know what i am doing wrong? I've been stuck on this for a while now, and can't seem to find the end of this :/.
from pythonforandroid.recipe import PythonRecipe
from pythonforandroid.toolchain import current_directory, shprint
import sh
class deepspeechRecipe(PythonRecipe):
version = 'v0.9.2'
url = 'https://github.com/mozilla/DeepSpeech/archive/{version}.tar.gz'
depends = ['numpy', 'setuptools']
call_hostpython_via_targetpython = False
site_packages_name = 'deepspeech'
def build_arch(self, arch):
env = self.get_recipe_env(arch)
with current_directory(self.get_build_dir(arch.arch)):
# Build python bindings
hostpython = sh.Command(self.hostpython_location)
shprint(hostpython,
'setup.py',
'build_ext', _env=env)
# Install python bindings
super().build_arch(arch)
def get_recipe_env(self, arch):
env = super().get_recipe_env(arch)
numpy_recipe = self.get_recipe('numpy', self.ctx)
env['CFLAGS'] += ' -I' + numpy_recipe.get_build_dir(arch.arch)
#env['LDFLAGS'] += ' -L' + sqlite_recipe.get_lib_dir(arch)
env['LIBS'] = env.get('LIBS', '') + ' -lnumpy'
return env
recipe = deepspeechRecipe()
Buildozer:1.4.0
requirements = python3==3.7.14, hostpython3==3.7.14, kivy, kivymd, sqlite3, numpy==1.14.5, deepspeech, apsw
If you need any extra information I can add.
I have already tried using tensorflow to run the model, however, the model gives an array as the output and I don't know the right procedures to transform that into a text form.
I have already tried other recipes (like opencv) and all work fine.
Edit:
I found out that when i use the recipe it does run, and it does build properly, but only the deepspeech_training part because the setup.py only installs that. To install other parts like the model class it is necessary to use another setup.py located in "native_client/python", but that requires the rest of the folders, so I still need to figure that out.
Edit2:I was able to build the packages that i wanted (the inference of deepspeech) however when i run it gives the following error.
python : ImportError: dlopen failed: library "libc++_shared.so" not found: needed by /data/user/0/org.test.myapp/files/app/_python_bundle/site-packages/deepspeech/_impl.so in namespace classloader-namespace
python : Python for android ended.
Add pillow in your requirements and check if it works!
requirements = python3==3.7.14, hostpython3==3.7.14, kivy, kivymd, sqlite3, numpy==1.14.5, deepspeech, apsw, pillow
I have some simple cefpython code opening a url and am trying to create a stand alone executable with pyinstaller:
I copied files from https://github.com/cztomczak/cefpython/tree/master/examples/pyinstaller to a a directry named pyinstaller
I made following minor changes to pyinstaller.spec
+SECRET_CIPHER = ""
...
- ["../wxpython.py"],
+ ["../hello.py"],
...
- icon="../resources/wxpython.ico")
+ )
I can successfully compile my application on windows with python
On the same machine with python 3.5.4 64 bit and following virtualenv:
cefpython3==66.0
future==0.18.2
PyInstaller==3.2.1
pypiwin32==223
pywin32==228
I can also compile windows with python 3.6.4 64 and following virtualenv:
altgraph==0.17
cefpython3==66.0
future==0.18.2
macholib==1.14
pefile==2019.4.18
PyInstaller==3.3.1
pyinstaller-hooks-contrib==2020.9
pypiwin32==223
pywin32==228
pywin32-ctypes==0.2.0
On Linux compilation works as well, but the executable is not operational.
I get following output and error:
CEF Python 66.0
Chromium 66.0.3359.181
CEF 3.3359.1774.gd49d25f
Python 3.5.2 64bit
[1013/180954.001980:ERROR:icu_util.cc(133)] Invalid file descriptor to ICU data received.
Trace/breakpoint trap (core dumped)
version is python 3.5.2 64bit and the virtualenv is:
cefpython3==66.0
pkg-resources==0.0.0
PyInstaller==3.2.1
What could be the cause?
The code, that I try to compile is below:
import platform
import sys
from cefpython3 import cefpython as cef
def check_versions():
ver = cef.GetVersion()
print("CEF Python {ver}".format(ver=ver["version"]))
print("Chromium {ver}".format(ver=ver["chrome_version"]))
print("CEF {ver}".format(ver=ver["cef_version"]))
print("Python {ver} {arch}".format(
ver=platform.python_version(),
arch=platform.architecture()[0]))
assert cef.__version__ >= "57.0", "CEF Python v57.0+ required to run this"
def main(url="https://www.stackoverflow.com"):
sys.excepthook = cef.ExceptHook
check_versions()
settings = {}
switches = {}
browser_settings = {}
cef.Initialize(settings=settings, switches=switches)
cef.CreateBrowserSync(
url=url,
window_title="CEF_HELLO: ",
settings=browser_settings,
)
cef.MessageLoop()
cef.Shutdown()
if __name__ == "__main__":
main()
Addendum: 2020-10-14:
same error on linux with other versions:
so far I tried python 3.5 and 3.7
Is there anybody who successfully created an executable?
I could be, that this just an issue with the example project and its configuration?
As alternative, a solution could be found in PyInstaller bug 5400
Here the steps:
1- download the PyInstaller helper in CEFpython named hook-cefpython3.py from:
https://github.com/cztomczak/cefpython/tree/master/examples/pyinstaller and put in the root directory of your project
2- In that file, replace the line:
from PyInstaller.compat import is_win, is_darwin, is_linux, is_py2
with:
from PyInstaller.compat import is_win, is_darwin, is_linux
is_py2 = False
3- in your PyInstaller .spec file, add the '.' to the hookspath, e.g. hookspath=['.']. I think it is also possible to add it as PyInstaller command line option.
These steps should solve the problem, until CEFPython deliver a correct version of the hook file.
This is not really the answer I would like to accept, but it is at least one solution and contains information, that might lead to a better fix, a better answer.
After debugging with strace I found out, that the executable searches many files like for example icudtl.dat, v8_context_snapshot.bin, locales/* were searched in
'dist/cefapp/cefpython3but were copied todist/cefapp/`
An ugly work around is to do following after compilation
cd dist/cefapp/cefpython3
ln -s ../* .
and the executable works.
I'm sure there is also a nicer non-brute-force solution, but for the time being I wanted to answer in case others are stuck as well
Probably this can be fixed in the spec file but would we need one spec file for linux and one for windows then?
Perhaps there's also an option to tell the excutable to search for these files one level higer?
To solve this, you need to set this in your spec file:
hookspath=[r'YOUR_ENV_SITE_PACKAGES\cefpython3\examples\pyinstaller\']
And then rebuild, you will have things in the right place.
The following steps solved the issue for me on Windows 10, Python 3.9.5 32-bit, PyInstaller 4.3, and CEFPython 66.1:
Download the hook-cefpython3.py file from here and put it into your project root directory.
Run the pyinstaller command as usual but add the --additional-hooks-dir . command line option, so the command will look like this:
pyinstaller --additional-hooks-dir . <main-file.py>
As opposed to other answers here, this anser neither requires changes of hookspath directive in pyinstaller's spec file and, as of now, nor any changes to the downloaded hook-cefpython3.py file.
I do this
C:\WINDOWS\system32>python c:\\python34\kissdownloader\setup.py bdist_wheel
and I get this after some other stuff
creating build\bdist.win-amd64\wheel\kissdownloader-1.dist-info\WHEEL
I goto my python root and there's nothing there , no build folder or anything . Is the thing somewhere else ? Oh and I don't have a manifest.in file if that makes any difference .
My setup.py file looks like this :
from setuptools import setup
setup (
name='kissdownloader',
version='1',
description = 'A kisscartoon/kissanime downloader' ,
package_dir={'kissdownloader':'C:\\Python34'},
author='Vriska',
author_email='xyz#gmail.com',
install_requires = ['bs4','cfscrape','requests'],
package_data={'data' : ['C:\Program Files\PhantomJS\phantomjs.exe']},
)
The output is generated in your current working directory. In your case, that's C:\WINDOWS\system32, because that's where you started Python. You'll find a build and dist directory; the latter contains the completed wheel.
If you want the directories to be created next to setup.py, change your directory to c:\python34\kissdownloader\ first. Many a Python project expects you to run setup.py there anyway.
As a side note: I wouldn't bundle the PhantomJS binary in with your project. Instead, require users to install it separately; they may already have it installed anyway, and you may run into legal issues by re-distributing it in your own project without at least a compatible license.
On one of my Windows 7 development machines, I am attempting to install the Python Image Library.
My machines are similar. Both run Windows 7 Professional, x64. Both use Python 2.7.3 (32bit). On one of the machine pip install PIL works fine. On the other it fails with the trace ending with this:
build\temp.win-amd64-2.7\Release\_imaging.pyd.manifest : general error c1010070:
Failed to load and parse the manifest. The system cannot find the file specified.
error: command 'mt.exe' failed with exit status 31
How can I resolve this error?
Thanks to http://bugs.python.org/issue4431, this error was fixed by modifying:
C:\<Python dir>\Lib\distutils\msvc9compiler.py
and adding:
ld_args.append('/MANIFEST')
after the MANIFESTFILE line so it looks like:
# Embedded manifests are recommended - see MSDN article titled
# "How to: Embed a Manifest Inside a C/C++ Application"
# (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx)
# Ask the linker to generate the manifest in the temp dir, so
# we can embed it later.
temp_manifest = os.path.join(
build_temp,
os.path.basename(output_filename) + ".manifest")
ld_args.append('/MANIFESTFILE:' + temp_manifest)
ld_args.append('/MANIFEST')
If you still get the error, then change the if arg.startswith("/MANIFESTFILE:") to if arg.startswith("/MANIFEST:") in the manifest_get_embed_info(self, target_desc, ld_args) method.
Download the compressed package from pypi, and try building and installing in your machine. This link could give you some hints. That exactly deals with your problem only but the installation varies.
If you've reached here looking for
general error c1010070:
Failed to load and parse the manifest. The system cannot find the file specified.
error: command 'mt.exe' failed with exit status 31
Here's a workaround that worked in Windows 8/x64/Python 3.3/VS 11:
# py 3.3 seems to be compiled against VS 2010 compiler, force using VS11 cl.exe for us
$env:VS100COMNTOOLS=$env:VS110COMNTOOLS
# Modify C:\Python33\lib\distutils\msvc9compiler.py
# Comment line 670: ld_args.append('/MANIFESTFILE:' + temp_manifest)
# Basically it will instruct build to not look for manifest file
I am writing a GUI application using python and Qt. When I launch my application on Mac, the first menu item in the Mac menu bar at the top of the screen is "Python". I would prefer the application name there to be the name of my application. How can I get my program name up there?
The following demo program creates a window with two menus: "Python", and "Foo". I don't like that, because it makes no difference to my users whether I wrote the app in python or COBOL. Instead I want menus "MyApp" and "Foo".
#!/usr/bin/python
# This example demonstrates unwanted "Python"
# application menu name on Mac.
# Makes no difference whether we use PySide or PyQt4
from PySide.QtGui import *
# from PyQt4.QtGui import *
import sys
app = QApplication(sys.argv)
# Mac menubar application menu is always "Python".
# I want "DesiredAppTitle" instead.
# setApplicationName() does not affect Mac menu bar.
app.setApplicationName("DesiredAppTitle")
win = QMainWindow()
# need None parent for menubar on Mac to get custom menus at all
mbar = QMenuBar()
# Add a custom menu to menubar.
fooMenu = QMenu(mbar)
fooMenu.setTitle("Foo")
mbar.addAction(fooMenu.menuAction())
win.setMenuBar(mbar)
win.show()
sys.exit(app.exec_())
How can I change that application menu name on Mac? EDIT: I would prefer to continue to use the system python (or whatever python is on the user PATH) if possible.
You seem to need an OSX .app for this to work, as the Info.plist file in there contains the user-visible name for the application that is put there. This defaults to Python, which is the title you see for the program menu. This blog post outlines the steps you need to take, while the OSX Developer Library has the docs on the property list you need to fill.
I have found the kernel of an answer to this question. Because I want to award the bounty to someone other than myself (I am the OP), please, anyone, take this kernel and elaborate it into a more complete answer of your own.
I can get the application menu to be "MyApp" as follows:
ln -s /System/Library/Frameworks/Python.framework/Versions/2.6/Resources/Python.app/Contents/MacOS/Python MyApp
./MyApp MyApp.py
There are two elements required to get this to work:
The symbolic link must be named "MyApp" (or whatever you want to appear in the Application Menu)
The symbolic link must point to the Python executable inside the system python app bundle. It does not work if you link to /usr/bin/python, for example.
There must be a clever way to create an app bundle or shell script that exploits this mechanism in a robust way...
If you intend to distribute the app, then symlinking the python binary is not guaranteed to work, considering that typically on development machines the system python is not the default python, and regular users most likely won't have Qt and PyQt installed.
A more reliable approach is to have a native OSX bootstrapping binary that would take care of starting your PyQt app. Both py2app and PyInstaller can generate native wrappers. While py2app worked well for creating an aliased app, i.e. a wrapper that symlinks to existing files on your system, getting it to bundle only the required PyQt dependencies proved to be non-trivial. Moreover the 'aliased app' generated by py2app with the --aliased flag will stop working if you move it to another folder since the symlinks are relative to the folder where you originally ran the build script.
PyInstaller
PyInstaller worked out-of-the-box and I ended up with an OSX bundle that included the dependencies all at around 16MB.
Bundle a python script to a standalone OSX app:
pyinstaller -w --noconfirm -i=myappicon.icns --clean -F myscript.py
This generates a standalone bundle that will display whatever you have in your .setWindowTitle() as the app name in the OSX title bar. The -w switch is important as it will create a MacOS app bundle with a proper .plist file.
NB: For some reason, the version of pyinstaller installed via pip did not work for me. So I removed the original pip version (pip uninstall pyinstaller), and installed the latest develop branch from github with:
pip install -v -e git+https://github.com/pyinstaller/pyinstaller.git#develop#egg=pyinstaller-github
After that it worked like a charm.
Mac Automator
Yet another option to create an app wrapper is to use Automator (type the name in Spotlight), go to File > New > Application > search for and drag Run shell script into the editor and under Shell select bash, python. You can also use the Run Applescript and bootstrap your app using apple script - can be useful if you need, for example, to ask the user's password in order to run with elevated privileges.
A better alternative to Automator is Platypus - a free and open-source app that wraps various types of scripts into OSX apps, and also provides some extra features like gui text output windows, running with admin privileges, setting custom icons, etc. The code is available on github.
There is also the option to create a barebones OSX app in Xcode that will launch your PyQt script (some examples here), and do other custom tasks required by your app.
NOTE: Keep in mind that an app bundle that calls your python code with a predefined interpreter is a 'shallow' app bundle, and will depend on whatever python dependencies you have install locally. Most likely will not work OOTB on someone else's Mac.
Nuitka
You might also want to try Nuitka (pip3 install nuitka) which aims to be a project to build truly native executables by converting your python code to C++ and then compiling it.
An example of building a native app with nuitka:
nuitka3 --follow-imports --python-flag=no_site --verbose --standalone --show-progress --show-modules --output-dir=my_build_dir myscript.py
This will create the mac executable with libraries in the my_build_dir folder. You will need to wrap them yourself in a MacOS app bundle, for example with Platypus or with Automator.
I know this isn't what the OP wants exactly, but figured it could add some value to searching for a solution to this issue.
You can make the file menus appear in your window UI instead of in the native Mac OS X system menubar:
menubar.setNativeMenuBar(False)
This will cause the menubar to appear as it would appear in e.g. Windows.
I would rather end users have access to my Python code so they and see and maybe improve on the code, so I am not interested in options that hide the code. I have found that I can get wx applications (have not tried with Qt) to run with a specified application name using different standard Python interpreters by wrapping them into a bundle as I install them (for example, as part of the conda package install process). Here is short script that creates an .app bundle with a specified name using the Python executing the script. Running the script using the created soft link (see pyAlias, below) as in
./MyApplication.app/Contents/MacOS/MyApplication /path/MyApplication.py
does the job.
from __future__ import division, print_function
import os,sys
appName = 'MyApplication' # name of app
scriptdir = '.'
iconfile = os.path.join(scriptdir,'MyApplication.icns') # optional icon file
if __name__ == '__main__':
wrapApp = os.path.join(scriptdir,appName+'.app','Contents')
os.makedirs(wrapApp)
wrapPy = os.path.join(wrapApp,'MacOS')
os.makedirs(wrapPy)
fp = open(os.path.join(wrapApp,'PkgInfo'),'w')
fp.write('APPL????\n')
fp.close()
fp = open(os.path.join(wrapApp,'Info.plist'),'w')
fp.write('''<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">\n<plist version="0.9">\n<dict>\n <key>CFBundleIconFile</key>\n <string></string>\n <key>CFBundlePackageType</key>\n <string>APPL</string>\n <key>CFBundleGetInfoString</key>\n <string>Created in makeApp.py (Brian Toby/QMake</string>\n <key>CFBundleSignature</key>\n <string>????</string>\n <key>CFBundleExecutable</key>\n <string>{:}</string>\n <key>CFBundleIdentifier</key>\n <string>com.continuum.python</string>\n <key>NSPrincipalClass</key>\n <string>NSApplication</string>\n</dict>\n</plist>\n'''.format(appName))
fp.close()
pyAlias = os.path.join(wrapPy,appName)
pythonpath = os.path.realpath(sys.executable)
os.symlink(pythonpath,pyAlias)
if os.path.exists(iconfile):
shutil.copyfile(iconfile,oldicon)
print('Use',pyAlias,'to run wxPython scripts')
Below is an older answer, which I am leaving for any historical value. In my application now, I use a hybrid between these where I create a drag-and-drop AppleScript bundle (as below) where I place a soft link to Python (named to match my app) as above.
Building on Christopher Bruns answer, as well as the script from "How to create Mac application bundle for Python script via Python", here is a Python script that creates a bundle (app) for an user Python script, which will show the app name rather than "Python" in the menus. To do this, it tries to locate a bundled version of Python, and symlinks to that with the name of the app. I tested it out with a wxpython script, but it should work for Qt as well.
The user script is run from its original location rather than placing it in the app. If you want to place your script(s) into a bundle (along with python) for redistribution, see py2app instead.
#!/usr/bin/env python
'''This creates an app to launch a python script. The app is
created in the directory where python is called. A version of Python
is created via a softlink, named to match the app, which means that
the name of the app rather than Python shows up as the name in the
menu bar, etc, but this requires locating an app version of Python
(expected name .../Resources/Python.app/Contents/MacOS/Python in
directory tree of calling python interpreter).
Run this script with one or two arguments:
<python script>
<project name>
The script path may be specified relative to the current path or given
an absolute path, but will be accessed via an absolute path. If the
project name is not specified, it will be taken from the root name of
the script.
'''
import sys, os, os.path, stat
def Usage():
print("\n\tUsage: python "+sys.argv[0]+" <python script> [<project name>]\n")
sys.exit()
version = "1.0.0"
bundleIdentifier = "org.test.test"
if not 2 <= len(sys.argv) <= 3:
Usage()
script = os.path.abspath(sys.argv[1])
if not os.path.exists(script):
print("\nFile "+script+" not found")
Usage()
if os.path.splitext(script)[1].lower() != '.py':
print("\nScript "+script+" does not have extension .py")
Usage()
if len(sys.argv) == 3:
project = sys.argv[2]
else:
project = os.path.splitext(os.path.split(script)[1])[0]
# find the python application; must be an OS X app
pythonpath,top = os.path.split(os.path.realpath(sys.executable))
while top:
if 'Resources' in pythonpath:
pass
elif os.path.exists(os.path.join(pythonpath,'Resources')):
break
pythonpath,top = os.path.split(pythonpath)
else:
print("\nSorry, failed to find a Resources directory associated with "+str(sys.executable))
sys.exit()
pythonapp = os.path.join(pythonpath,'Resources','Python.app','Contents','MacOS','Python')
if not os.path.exists(pythonapp):
print("\nSorry, failed to find a Python app in "+str(pythonapp))
sys.exit()
apppath = os.path.abspath(os.path.join('.',project+".app"))
newpython = os.path.join(apppath,"Contents","MacOS",project)
projectversion = project + " " + version
if os.path.exists(apppath):
print("\nSorry, an app named "+project+" exists in this location ("+str(apppath)+")")
sys.exit()
os.makedirs(os.path.join(apppath,"Contents","MacOS"))
f = open(os.path.join(apppath,"Contents","Info.plist"), "w")
f.write('''<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>main.sh</string>
<key>CFBundleGetInfoString</key>
<string>{:}</string>
<key>CFBundleIconFile</key>
<string>app.icns</string>
<key>CFBundleIdentifier</key>
<string>{:}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>{:}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>{:}</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>{:}</string>
<key>NSAppleScriptEnabled</key>
<string>YES</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>
'''.format(projectversion, bundleIdentifier, project, projectversion, version)
)
f.close()
# not sure what this file does
f = open(os.path.join(apppath,'Contents','PkgInfo'), "w")
f.write("APPL????")
f.close()
# create a link to the python app, but named to match the project
os.symlink(pythonapp,newpython)
# create a script that launches python with the requested app
shell = os.path.join(apppath,"Contents","MacOS","main.sh")
# create a short shell script
f = open(shell, "w")
f.write('#!/bin/sh\nexec "'+newpython+'" "'+script+'"\n')
f.close()
os.chmod(shell, os.stat(shell).st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
I think you need to do this:
win.setWindowTitle("MyApp")
Edit: This is for PyQt. I don't know the equivalent in PySide.