Python - running script is in an egg? - python

i created an executable egg to make it as an single file executable.
setup.py:
#!/usr/bin/env python
from setuptools import setup, find_packages
setup(
name='app',
version='0.5',
description='foo',
author='microo8',
author_email='xxx#email.com',
packages=["foo", "bar"],
install_requires=["sqlalchemy>=0.7", "paramiko>=1.7.7.1"],
entry_points = {
'setuptools.installation': [
'eggsecutable = foo.module:main',
]
}
)
I can now call it: ./app-0.5-py2.7.egg, but the relative paths are all in the egg.
when I call print __file__ in the main function it prints /home/user/app-0.5-py2.7.egg/foo/module.py. I want to read an config file that must be in the same dir as the egg. And the same script must be executable also as "non-egg", so the config file will be in the dir with the script.
how can i find out that the script is executed from an egg and also the egg path?

So I dont know how to check that the running script is in an egg, but the config file path can be obtained with this: os.path.realpath('config.cfg').
This suits me and when I have a dir with the executable egg and an config file this is a correct path.
Also when I have just the script in the dir with the config file it also is correct.
And also when i use pyinstaller to create an singlefile exe.

You should load your configuration file using the ResourceManager API. That way your eggified code can load the configuration file even when zipped.
import pkg_resources
configdata = pkg_resources.resource_string(__name__, "myconfigfile.cfg")
The API can check for existence, test for directories, read data or provide you with an open file object for any resource that is part of your egg.
The API takes care of all the details; it'll extract files to a temporary directory for example, if you absolutely must have a filename for a resource but are running from a zipped egg.
Most of all, it'll work regardless of whether or not you are in fact installed as an egg or stand-alone.

Related

get the path of the executed file once "compiled" with pyinstaller

I know there are a lot of answers on this subject, but no one works once you compile a script in an executable.
In my python script, I create a file within the same directory of the script.
to get the path of the current dir I use pathlib
basepath = Path(__file__).parent
filename='myfile'
filepath=os.path.join(basepath, filename)
if I print the directory I get the file wrote in the good directory and everything works fine within python
(i.e desktop/myname/myscriptdir/myfile)
but once I "compile" with pyinstaller with --onefile, if I launch the executable, the directory will be
like
/var/folders/nr/w0698dl96j39_fq33lqd8pk80000gn/T/_MEIP12KxC/myfile
believed me, I tried a lot of various method (abspath, os.realpath..)to get the current dir, no one worked fine once in an executable file.
When you compile an app using pyinstaller with the --onefile or -F flag, the file that it creates is actually an archive file, like a .zip file.
When you execute that file it launches a process that extracts itself into a temporary folder somewhere in your OS filesystem. This is the path that is reported when you use the __file__ variable in the compiled application.
It then continues to launch your application from there and the temporary directory becomes the runtime durectory for the duration of the apps life. When the app is finally closed it deletes the temporary runtime directory on it's way out.
Since this is the case there are alternatives.
To get the current working directory during runtime use:
path = '.'
#or
path = os.getcwd()
To get the path to the compiled executable file during runtime:
path = sys.executable

imported python module from another directory fails

I have imported a python module from another directory in Linux by using sys.path.insert but when I run that module it fails. As the imported module is trying to open a file that is local to that module. Please let me know how to fix this.
users/adr/release/invoke.py #this one fails with can’t open file ./config.ini
import sys
sys.path.insert(0, ‘/user/cdw/audit/’)
import audit_main
The path where the original module file resides.
/user/cdw/audit/audit_main.py # this module opens config.ini file to read pplication credentials.
/user/cdw/audit/config.ini
/user/cdw/audit/__ini__.py
When python loads a module it adds metadata to its global namespace that can be used by the module. __file__ is the filename of its .py file - when such a name makes sense. You can use it to get your config file
import os
config_filename = os.path.join(os.path.dirname(__file__), "config.ini")
except for when you can't. If this is a C extension file or if the file was in some other packaging like zip or egg or pyinstaller bundle or exe, it may not work. A ini file, which I assume is user editable, may need to be some place other than the module directory. If you make this .py part of an installable package, it may end up in a system directory the user can't edit. This may not be a problem for this project, just laying out some of the considerations.

Irerate over package_data files and copy them to current working directory

Background
I'm developing a python package with roughly the following directory structure:
mossutils/
setup.py
mossutils/
__init__.py
init.py
data/
style.css
script.js
...
My package's setup.py declares console_scripts and includes package_data files:
setup(
name='mossutils',
packages=['mossutils'],
package_data={"mossutils": ["data/*"]},
entry_points = {
"console_scripts": ['mu-init = mossutils.init:main']
},
...)
Installing the package via pip install works as expected: everything is installed in my Python's Lib\site-packages, including the data directory and all files in it, and script mu-init can be executed from the shell (or rather, command prompt, since I'm using Windows).
Goal
Script mu-init is supposed to do some kind of project scaffolding in the current working directory it is invoked from. In particular, it should copy all package_data files (data/style.css, data/script.js, ...) to the current directory.
Solution Attempt
Using module pkgutil, I can read the content of a file, e.g.
import pkgutil
...
data = pkgutil.get_data(__name__, "data/style.css")
Questions
Is there a way for my init.py script to iterate over the contents of the data directory, without hard-coding the file names (in init.py)?
Can the files from the data directory be copied to the current working directory, without opening the source file, reading the content, and writing it to a destination file?
You can get the list of files in the directory using pkg_resources library, which is distributed together with setuptools.
import pkg_resources
pkg_resources.resource_listdir("mossutils", "data")

Creating an egg file generates only EGG-INFO folder

I have a python file named file_processor.py. I would like to create an egg file out of this python file to use it in another projects. My setup.py file looks as following:
from setuptools import setup, find_packages
setup(
name = "file_processor",
version = "0.5",
packages = find_packages()
)
And I run this script with the following command:
python setup.py bdist_egg
This command generates 3 folders, namely: build, dist, file_processor.egg-info. My .egg file is located in the dist folder. However, if I change its extension from .egg to .zip to see the contents, I find only one folder which is EGG-INFO, and not the actual python file. An so, if I try to add that .egg file into my project path and import file_processor module, python throws an error that no module named file_processor found. What am I doing wrong here? Note: I got the information for generating egg files from this link
Wheel files are generally preferred over eggs these days.
Regardless, I would guess that you don't have the file_processor.py in a separate directory and you have it in the same directory as the setup.py, it needs to be in it's own directory.
You should also include a __init__.py in that directory, inside the file you can put
from .file_processor import *
This will import all the functions from your file into the package so you can use them.
This tutorial is quite good if you're looking for more information https://python-packaging.readthedocs.io/en/latest/minimal.html

setup.py not create proper folders/configuration in mac osx?

I am trying to create the setup.py for a script. The setup.py looks like this:
from setuptools import setup
setup(name='readfile',
version='1.0',
description='A flexible module to read ascii files',
author='author',
author_email='author#gmail.com',
url='',
modules=['readfile'])
the script is called readfile.py and doesn't have any additional files or scripts. All I want to do is have setup.py put it on the correct location automatically. So I do
python setup.py install
This creates a folder
/Library/Python/2.7/site-packages/readfile-1.0-py2.7.egg
However, it doesn't update the python path nor create a directory called readfile in site-packages directly, so I cannot import the module. Am I missing an option that would do any of these?
Thanks!
EDIT:
I had some more trouble afterwards; with various combinations of setup() arguments I was able to import readfile but none of its modules. In the end, the setup.py was fine and I just needed the __init__.py, without the extra folder. So the three files (readfile.py, setup.py, __init__py) are in the same folder now and everything works as it should.
Do you have a folder at the same level as setup.py called readfile?
Inside that, is there a file called __init__.py?
Inside that folder is there also your source file called readfile.py?
That seems to work for me.
The .egg file that you reference is just a zip file that contains everything you need. There should be no need to update python path or create the readfile directory. Those things are not needed to import readfile.

Categories