I have just started writing some simple scripts in python as I've started using ubuntu as my default operating system.
So I came across the code for mpsyt (terminal youtube player). I was surprised how simple the coding was. Could anybody explain what is going on here? I don't undestand how a seemingly complex program could have such a small amount of code....
#!/usr/bin/python3
# EASY-INSTALL-ENTRY-SCRIPT: 'mps-youtube==0.2.5','console_scripts','mpsyt'
__requires__ = 'mps-youtube==0.2.5'
import sys
from pkg_resources import load_entry_point
if __name__ == '__main__':
sys.exit(
load_entry_point('mps-youtube==0.2.5', 'console_scripts', 'mpsyt')()
)
This is an autogenerated stub; it executes an entry point in the mps-youtube package installed in your site-packages. It is not the actual script.
The setuptools project installs such stubs in the bin directory; it's task is to find the right version of the project and load the real script.
There will be a matching lib/python[version]/mps-youtube-0.2.5-py[version].egg-info directory holding metadata, including an entry_points.txt file that contains INI-file-format style information on the package. The load_entry_point('mps-youtube==0.2.5', 'console_scripts', 'mpsyt') line will look for that exact file to load the mpsyt definition from the console_scripts section.
In the [console_scripts] section there will be a mpsyt entry that names the actual module used to run the script. Judging by the project setup.py file that'll look like this:
[console_scripts]
mpsyt = mps_youtube:main.main
pointing to the mps_youtube.main module, where the main() function will be called to do the actual work; look for a lib/python[version]/mps_youtube/main.py file, then search for a def main(): function definition. From Github you can see the actual script is a little longer.
This isn't the entire program. This just runs the rest of the program.
Related
I'm working on distributing a Python package. It depends on the library lupa. I want to run a post-install script that depends on lupa that initializes some data within the package after it's been installed. After looking at some answers around StackOverflow, my stripped setup.py essentially looks like this:
# setup.py
from distutils.core import setup
from setuptools.command.install import install
class PostInstallCommand(install):
def run(self):
# Do normal setup
install.run(self)
# Now do my setup
from mymodule.script import init
init()
setup(
# ...
install_requires = [
# ...
"lupa >= 1.10",
# ...
],
cmdclass = {
'install': PostInstallCommand
}
)
However, when emulating a fresh install/setup with tox on Python 3.10, I get this error:
File "C:\My\Computer\Temp\pip-req-build-pl0jria3\setup.py", line 26, in run
from mymodule.script import init
File "C:\My\Computer\Temp\pip-req-build-pl0jria3\mymodule\script.py", line 28, in <module>
import lupa
ModuleNotFoundError: No module named 'lupa'
I was under the impression that anything put into install_requires would be installed by the time setup() finished, but that appears not to be the case (also corroborated by this answer). Is there anything I can do to ensure that lupa is installed prior to mymodule.script.init(), or is that stage of the setup process entirely out of the user's hands?
After doing a good bit of research, it seems this kind of post-install script is somewhat against the core philosophy of setuptools, which means that a request like this is unlikely to be added, or at least added anytime soon.
Fortunately, this is somewhat of a blessing in disguise; my post-install script is actually an "update" console entry point that the user calls anytime they've added mods or updated any of the packages data. This script can be (and is supposed to be) called many times by the user, so by having it as part of the install process it helps introduce the purpose of the script to the user right from the start. This makes the slight annoyance on install tolerable, at least in my circumstance.
I created a project that follows the example in MutPy's README file.
However, when I run mut.py --target calculator --unit-test test_calculator -m, it just opens mut.py instead of actually running MutPy.
The file has the following content:
#!c:\users\admin\appdata\local\programs\python\python39\python.exe
import sys
from mutpy import commandline
if __name__ == '__main__':
commandline.main(sys.argv)
The README doesn't mention any other configurations that need to be done and says that it should be compatible with Python 3.3+ (I'm on Python 3.9.6).
Is there something I'm doing wrong?
Are you runing this from cmd.exe?
If so try:
python.exe mut.py --target calculator --unit-test test_calculator -m
Note that you need python in your PATH Variable.
It will probably also work if you set python as the default application for .py files.
I have a code which I'd like people to be able to use as a stand alone python program, or to import as a module for their own codes. Is there a way to package a module which can also include a program that can be run from the command line?
I.e. from the command-line:
> ZHermesCode
or within ipython or a python script:
import ZHermesCode
Look up Setuptools automatic script creation. For example, python-scss uses this technique to make scss an executable shell command.
In setup.py:
setup(
# ...
entry_points={
'console_scripts': [
'scss = scss.tool:main',
]
},
)
Then defining a function main in scss/tool.py. It also uses the technique mentioned by Loocid to make the tool.py file itself directly executable (as opposed to the wrapper script that is publicly installed by setuptools according to the recipe above):
if __name__ == '__main__':
main()
If you use:
if name == '__main__':
The code held in that 'if' statement will only be ran if someone runs your program from the command line.
If someone was to import your module instead, the code will not run.
Eg
def test(st):
return(st)
if name == "__main__":
print(test("hello"))
If you run this program from the command line, it will print "hello". However, someone could also import this module and have access to the "test" function to use in their own programs.
I am newbie in python.
Could anybody answer what does __requires__ means in the following code?
Why would they put __requires__ = 'flower==0.4.0' in the beginning of the file?
#!/srv/virtualenvs/zeusenv/bin/python
__requires__ = 'flower==0.4.0'
import sys
from pkg_resources import load_entry_point
sys.exit(
load_entry_point('flower==0.4.0', 'console_scripts', 'flower')()
)
The __requires__ line is part of a generated console script. It has no meaning to Python itself, only the setuptools library uses this information.
Console scripts are python scripts defined in a python package metadata, and setuptools installs wrapper script files to let you run them as command line scripts. The flower file installed in your virtualenv is such a script, defined by the flower package setup.py file.
The pkg_resources module imported in the wrapper script inspects the value of __requires__ in the main script to make sure the correct version of the library is available and loaded before the load_entry_point function (or any other pkg_resources function) is run. It'll not install the version specified, it is assumed that that version is already installed on your system. It's purpose is to avoid loading incorrect, incompatible resources when the script runs and loads dependencies.
Ok - here goes. I am trying to learn how to use py2app, so I created a simple python file; just hello_world.py
#! /usr/bin/env python
def main():
print "Hello"
if __name__=="__main__":
main()
I followed a tutorial and did the following:
py2applet --make-setup hello.py
python setup.py py2app -A
This created two sub-directories (build and dist), within dist there was a file called hello.app. I attempted to launch it through the GUI but it launched for less than a second and then disappeared. I then went to the CL but simply trying to run it didn't work so I used:
python hello.app
with the following error:
/Library/Frameworks/Python.framework/Versions/2.6/Resources/Python.app/Contents/MacOS/Python: can't find '__main__.py' in 'hello.app'
I've spent all day googling but can't find any tutorials or guides etc. I'm really stuck :-(
I don't know if this helps but this is what is in the setup.py
"""
This is a setup.py script generated by py2applet
Usage:
python setup.py py2app
"""
from setuptools import setup
APP = ['hello.py']
DATA_FILES = []
OPTIONS = {'argv_emulation': True}
setup(
app=APP,
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
)
You have successfully used py2app - it just opens, prints "hello" and then closes really quickly!
If you want to see something, then make it pause for a bit:
print "Hello"
import time
time.sleep(5)
time.sleep pauses a program for the number of seconds given.
You really only want to use py2app with GUI apps, or ones that run in the background.
If you want to run the py2app-built application from the command line, you need to execute the binary inside the application bundle; the bundle itself is not directly executable, so something like this:
dist/hello.app/Contents/MacOS/hello
For scripts that just print to stdout you might try Platypus (though it doesn't do the dependency-packaging stuff of py2app).
It seems that it was working all along - the script was just running so quickly I didn't have a chance to see it. If anyone comes across this go to http://svn.pythonmac.org/py2app/py2app/trunk/doc/index.html and follow the tutorial. Please also read the answers given and the replies I left.