Terminal says "PyObjCTools" doesn't exist when it does - python

I am attempting to build a Python application on OSX 10.10, I have used MacPorts to install all dependencies and have used PyCharm to write the application. When I run it from PyCharm everything works fine, but when I try to run the build script, when it comes to the py2app part it tells me that the directory ".../PyObjC/PyObjCTools" isn't there, but I can navigate to it in Finder and it's very clearly there. Does anyone have any idea what my problem could be? I've been running around in circles with this for a week now.

If it's access to the PyObjCTools functionality you want, you should import it the Python way, for example:
from PyObjCTools import AppHelper
If you need to access actual files, it's possible to force py2app to add files using the setup data_files options. For example:
from setuptools import setup
setup(
app=['main.py'],
name="App Name",
data_files=['/path/to/folder'],
setup_requires=['py2app'],
options=dict(py2app=dict(iconfile='en.lproj/icon.icns',
includes=['includename'],
packages=['packagename']
)
)
)
After a rebuild the files are located inside the Cocoa bundle Resources folder, which you can find using the resourcePath() function:
NSBundle.mainBundle().resourcePath()

Related

How to make a Python exe file automatically install dependancies?

I have made an application using python using some libraries installed as needed on the go. Now I want to make it usable for person who doesn't know how to install dependencies and which ones are needed.
What to do to transform it into an easy to use application and probably make it able to run on Mac too??
Please suggest some resources that might help me know more.
PyInstaller might be something you are looking for, which can create .exe files from python scripts.
Here's the documentation. Be aware that the __import__() function with variable data isn't detected by PyInstaller, so you should just use import ..., and then PyInstaller will add the dependencies so that they are used in the .exe file.
As Wouter K mentioned, you should install Pyinstaller (pip install pyinstaller for pip) and then cd to the directory you want and type pyinstaller --onefile file.py on the terminal. If you cded in the directory your file is, you just type the name and the extension (.py) of your file. Else, you will have to specify the full path of the file. Also, you can't make an mac os executable from a non mac os pc. You will need to do what I mentioned above on a mac.
When making the executable you should declare the modules with it, you can then just copy the library files to the same location as the programme.
I use cx_freeze when making exe's and an example setup.py files looks like this:
from cx_Freeze import setup, Executable
base = None
executables = [Executable("projectname.py", base=base)]
packages = ["idna","os","shutil","csv","time","whatever else you like"]
options = {
'build_exe': {
'packages':packages,
},
}
setup(
name = "Some Project",
options = options,
version = "1.2.3",
description = 'Generic Description',
executables = executables
)
Packages are where the modules are declared.
If you have a quick search online it'll give you complete guides for it, all you'd need to do then is copy the lot across to your friend's computer.
Hope this helps!

How to convert a pygame application with multiple modules to .exe

I have a pygame application which I would like to convert to .exe format.
Pygame2exe (https://pygame.org/wiki/Pygame2exe) works nicely EXCEPT I am unable to figure out how to do this conversion with a project that has more than one custom module.
For example:
python_project/
main.py
other.py
I need to compile both modules, and merging them is not an option.
I have been working at this problem for a few weeks, and have not found any solutions.
I know it is possible, because I had it working, and then formatted the only hard drive that had a copy of the code without realizing I had not made a backup.
EDIT
Thank you Michael.
I just had to make a small change to the setup.py file you provided to make it font compatible. Here is the full setup.py file
from distutils.core import setup
import py2exe
import os
origIsSystemDLL = py2exe.build_exe.isSystemDLL
def isSystemDLL(pathname):
if os.path.basename(pathname).lower() in ["sdl_ttf.dll"]:
return 0
return origIsSystemDLL(pathname)
py2exe.build_exe.isSystemDLL = isSystemDLL
setup(windows=['main.py'])
(taken from Pygame font not working after py2exe)
Thanks again.
if you are using python 3.3 or 3.4, you can use py2exe.
install through pip, pip install py2exe in cmd
note: if 'pip' is not recognized as an internal or external command, navigate to the directory in which python is installed,/scripts probably: C:\python34\scripts
make a setup script called setup.py,
with just the three lines of code
from distutils.core import setup
import py2exe
setup(windows=['filename.pyw'] #probably pyw in windows, will be name of main file
then open command prompt in the directory where the main file and setup.py are located, and type setup.py py2exe
DO NOT USE or filename.pyw in the setup script, use the name of the main module.
this will make a folder called dist, (you can safely get rid of '__pycache_') containing all the files your exe needs to run!
you will probably want to make an installer, I would recommend Inno Setup (http://www.jrsoftware.org/isinfo.php)

How can we build and distribute python scripts in a windows environment

My team is enjoying using python to solve problems for our business. We write many small independent scripty applications.
However, we have to have a central windows box that runs these along with legacy applications.
Our challenge is going through a build and deploy process.
We want to have Bamboo check the script out of git, install requirements and run tests, then if all is green, just deploy to our production box.
We'd like libraries to be isolated from script to script so we don't have dependency issues.
We've tried to get virtualenvs to be portable but that seems a no go.
Pex looked promising, but it doesn't work on windows.
Ideally you'd see a folder like so:
AppOne
/Script.py
/Libs
/bar.egg
/foo.egg
AppTwo
/Script2.py
/Libs
/fnord.egg
/fleebly.py
Are we thinking about this wrong? What's the pythonic way to distribute scripts within an enterprise?
You may be able to do that with a neat if relatively unknown feature that was sneaked into Python 2.6 without much ado: executing zip files as Python applications. It got a bit (just a bit) more of publicity after PEP 441 (which is the one PEX is inspired in), although I think most people is still unaware of it. The idea is that you create a zip file (the recommeded extension is .pyz or .pyzw for windowed applications, but that's obviously not important) with all the code and modules that you want and then you simply run it with Python. The interpreter will add the contents of the zip file to sys.path and look for a top level module named __main__ and run it. Python 3.5 even introduced the convenience module zipapp to create such packaged applications, but there is really no magic in it and you may as well create it by hand or script.
In your case, I guess Bamboo could do the check out, dependency install and tests in virtualenvs and then package the application along with the environment libraries. It's not a one-click solution but it may do the trick without additional tools.
TL:DR:
Use Docker
A short story long:
You can use docker to create an independent image for every script that you want to deploy.
You can install a python image (slim is the lightest) as a base environment for each script or a group of scripts/applications and use it like a "virtualenv" in which you can install all your dependencies for that script.
There is also an integration for Bamboo and Docker which you may find useful.
Here is the Docker documentation for reference.
You can test each script individually in a separated container and if it passes then you can use the same container to deploy it in your main server.
It is not exactly what you are asking, but you can use this solution in every platform (Windows, Linux, etc.), you can deploy all your scripts to the enterprise server (or anywhere for that matter) and use them across your company.
Disclaimer: This is not THE solution, it is a solution that I am aware of which applies to the time of this answer (2017)
Another possibility is pyinstaller. It creates an executable that can be deployed. Python is not even required to be installed on the deployed production box. It is harder to debug problems that occur only on the deployed box. You also can't modify the scripts on the deployed box which depending on your trust of the owners of the machine is either a positive or negative. See http://www.pyinstaller.org/
As I understand it, you want to create self-contained application directories on a build server, then copy them over to a production server and run scripts directly from them. In particular, you want all dependencies (your own and external packages) installed within a Libs subdirectory in each application directory. Here's a fairly robust way to do that:
Create the top-level application directory (AppOne) and the Libs subdirectory inside it.
Use pip install --ignore-installed --target=Libs package_name to install dependencies into the Libs subdirectory.
Copy your own packages and modules into the Libs subdirectory (or install them there with pip).
Copy Script.py into the top-level directory.
Include code at the top of Script.py to add the Libs directory to sys.path:
import os, sys
app_path = os.path.dirname(__file__)
lib_path = os.path.abspath(os.path.join(app_path, 'Libs'))
sys.path.insert(0, lib_path)
This will make packages like Libs\bar.egg and modules like Libs\fleebly.py available to your script via import bar or import fleebly. Without code like this, there is no way for your script to find those packages and modules.
If you want to streamline this part of your script, there are a couple of options: (1) Put these lines in a separate fix_path.py module in the top-level directory and just call import fix_path at the start of your script. (2) Create a Libs\__init__.py file with the line sys.path.insert(0, os.path.dirname(__file__)), and then call import Libs from your script. After that, Libs\x can be imported via import x. This is neat, but it's a nonstandard use of the package and path mechanisms (it uses Libs as both a library directory and a package), so it could create some confusion about how importing works.
Once these directories and files are in place, you can copy this whole structure over to any Windows system with Python installed, and then run it using cd AppOne; python Script.py or python AppOne\Script.py. If you name your top-level script __main__.py instead of Script.py, then you can run your app just by executing python AppOne.
Further, as #jdehesa pointed out, if your script is named __main__.py, you can compress the contents of the AppOne directory (but not the AppOne directory itself) into a file called AppOne.zip, and then copy that to your production server and run it by calling python AppOne.zip. (On Python 3.5 or later, you can also create the zip file via python -m zipapp AppOne if your script is called __main__.py. You may also be able to use python -m zipapp AppOne -m Script if your script is called Script.py. See https://docs.python.org/3/library/zipapp.html.)
This kind of thing can be easily dealt with python setup.py
Sample setup.py
from setuptools import setup
setup(
name=name_for_distribution,
version=version_number,
py_modules=[pythonfiles],
install_requires=[
python packages that need to be installed
]
)
Create a virtual environment , activate it and run :
python setup.py install
I feel this is the most pythonic way to distribute and package your project.
Reading links:
https://pythonhosted.org/an_example_pypi_project/setuptools.html
https://docs.python.org/2/distutils/setupscript.html

Python portable pyinstaller

I'm building an application where I'd like my users to be able to create executables with only a couple of clicks for some settings. It's a GUI application made with Tkinter where there is a page with some options. These options are then supposed to be written to a premade Python script. That will be no problem to make. The tricky part is compiling the script into an executable (.exe). I've always been using PyInstaller for making executables, but that's only on my own local computer. What if I want to pack my application and have PyInstaller bundled? I know PyInstaller requires pywin32, which means that has to be bundled too.
I'm completely lost on how to bundle PyInstaller with my application.
I've been doing a lot of googling on the matter, but can't seem to find any help at all. The closest I got was this post, which didn't help very much.
Try to use Nuitka. I tried some alternatives for Python (including PyInstaller) and like this one most. With Nuitka you can compile your script (and all modules it need) to standalone .exe file. Then you can create installer with many available options.
Here's user manual, here's example of command (I used for my project):
nuitka --standalone --recurse-all --recurse-stdlib --remove-output --windows-disable-console --recurse-directory=YOUR_PROJECT_DIR
Upd:
How to run nuitka inside script:
import os
import subprocess
project_dir = os.path.abspath('project')
project_main = os.path.abspath('project\\main.py')
subprocess.call([
'nuitka', '--standalone', '--recurse-all', '--recurse-stdlib', '--remove-output',
'--windows-disable-console',
# '--windows-icon={}'.format(icon_path),
'--recurse-directory={}'.format(project_dir),
project_main
], shell=True)

Bundle python tool in Cocoa app with easy_install

My Cocoa app requires a Python command line tool to be installed on the user's system using easy_install. Ideally, I'd want to bundle one bash file with my app which I can then run. But as far as I know this is not possible, because packages are installed in the "site-packages" directory of Python.
Is there a way to create a "package" of those files?
If not, how should I run the easy_install installation? I wanted to bundle a .pkg file with my app which I can then open if necessary, but I wasn't able to let this installation package run a script only.
If you have ideas on how to fix this, I'd be glad.
Kind regards,
Fabian
If you can ship the command line tool with your application, and if only your application will be using it (instead of the tool being used directly by the user), you can directly include and use the command line tool with your application like so:
Store the command line tool somewhere in your application directory.
Set the Python module search path so that it looks for the module you need.
Setting the Python module search path relative to a Python program can be done with
import sys
import os.path as path
sys.path.append(path.join(path.dirname(__file__),
'<relative path between this program and the command line tool module>'))
import <command line tool module>
The relative path can be written with the .. parent directory convention: this works both on Unix (including Mac OS X) and Windows.
PS: If many programs need to access the command line tool module, you can:
Either put the above code in each of your programs,
or, if you want something easier to maintain, you can create your own module my_runner and use it as a proxy: your module my_runner would import all the original runner functions like so:
import sys
import os.path as path
sys.path.append(path.join(path.dirname(__file__),
'<relative path between this program and the original ino module>'))
from ino.runner import *
You can then use the original runner module in all your programs through your proxy, by simply doing "normal" imports of your own my_runnermodule:
from my_runner import main
PPS: If you want a more robust path that works even if the working directory later changes, it is possible to convert a potentially local path to an absolute path with: path.join(path.abspath(path.dirname(__file__)),….
Thanks to EOL I got it working now. The solution involved several steps listed below.
Remove dependencies by packaging the .egg files and referencing them like this:
import sys
import os.path as path
sys.path.append(path.join(path.dirname(__file__), '<relative path to .egg file>'))
from dependency import something
Build a single .egg file from the now independent python module using setup.py
Reference the resulting .egg file in the command line tool like in 1.
Bundle the single .egg file and the command line tool in the Cocoa app
I hope this will be useful to someone.

Categories

Resources