I'm trying to bundle my py script as an .exe using PyInstaller 2.0. I am able to bundle the script, but in my script, I need to open a file that should be bundled in the exe (so it's portable). I'm having trouble doing this..
In my .py, I have
filename = 'C:\path\to\my\file\doc.docx'
data = open(filename,'rb')
I use PyInstaller 2.0 and this works fine on my computer, but if I transfer the exe to another computer it isn't going to work.. PyInstaller 2.0 is pretty new, so there are very few documents on it, and the publisher's documentation is quite "lacking."
Here is the publisher's info on the matter: (I don't think their documentation is up to date, because in the beginning it says use Configure.py, then in other docs it says Configure.py is no longer needed in 2.0)
In a --onefile distribution, data files are bundled within the executable and then extracted at runtime into the work directory by the C code (which is also able to reconstruct directory trees). The work directory is best found by os.environ['_MEIPASS2']. So, you can access those files through:
os.path.join(os.environ["_MEIPASS2"], relativename))
That doesn't really make sense to me, a beginning programmer..
A different document from the publisher says..
In a --onefile distribution, data files are bundled within the executable and then extracted at runtime into the work directory by the C code (which is also able to reconstruct directory trees). The work directory is best found by sys._MEIPASS. So, you can access those files through:
os.path.join(sys._MEIPASS, relativename))
I've experimented around quite a bit with os.environ["_MEIPASS2"] and python doesn't seem to understand os.environment["_MEIPASS2"]. I get this back:
>>> print os.environ["_MEIPASS2"]
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
print os.environ["_MEIPASS2"]
File "C:\Python27\lib\os.py", line 423, in __getitem__
return self.data[key.upper()]
KeyError: '_MEIPASS2'
I also experimented with sys._MEIPASS.. Yeah, python responds 'module' has no attribute '_MEIPASS'.
At this point, I feel like my head is about to explode.. I appreciate PyInstaller's authors for their work, but their documentation is the worst I've ever seen! I just need someone to help me bundle my file into the exe. I would really like to use PyInstaller 2.0+ since all the .spec stuff confuses me with previous versions of PyInstaller.
BTW, I'm using Win8 64bit with python 2.7.3
PLEASE HELP!
When we specify the onefile option, to the PyInstaller, it unpacks all the files to a TEMP directory, executes the file, and later discard the TEMP folder. When you specify the add-data option along with onefile, then you need to read the data referred to in the TEMP folder.
pip will install PyInstaller's dependencies along with a new command: pyinstaller . PyInstaller can be imported in your Python code and used as a library, but you'll likely only use it as a CLI tool. You'll use the library interface if you create your own hook files.
PyInstaller bundles a Python application and all its dependencies into a single package. The user can run the packaged app without installing a Python interpreter or any modules. PyInstaller reads a Python script written by you.
To bundle your project into a single file, you can build with a command like this: $ pyinstaller cli.py --onefile With the above command, your dist/ folder will only contain a single executable instead of a folder with all the dependencies in separate files.
There are some applications all packed by pyinstaller2.0 with --onefile option on windows. One of them call others through subporcess, but the others can't startup. The other applications work when startup through cmd or other applications not packed by pyinstaller2.0. pyinstaller 1.5 works.
PyInstaller bundles a Python application and all its dependencies into a single package. The user can run the packaged app without installing a Python interpreter or any modules. PyInstaller supports Python 3.7 and newer, and correctly bundles many major Python packages such as numpy, matplotlib, PyQt, wxPython, and others.
You have to add your image files in "datas" (either in your spec files or with a PyInstaller hook script) using the single line base_path = getattr (sys, '_MEIPASS', '.')+'/' to get a "root_path" variable to concatenation to all your files' paths. Add "datas = ['Location of your file']," before "hiddenimports = []". It will do.
OMG! This PyInstaller really confused me for a bit. If my previous post sounds a little "ranty", sorry about that.. Anyways, for anyone trying to include a file in a --onefile PyInstaller package this worked for me:
Include this in your .py script:
filename = 'myfilesname.type'
if hasattr(sys, '_MEIPASS'):
# PyInstaller >= 1.6
chdir(sys._MEIPASS)
filename = join(sys._MEIPASS, filename)
elif '_MEIPASS2' in environ:
# PyInstaller < 1.6 (tested on 1.5 only)
chdir(environ['_MEIPASS2'])
filename = join(environ['_MEIPASS2'], filename)
else:
chdir(dirname(sys.argv[0]))
filename = join(dirname(sys.argv[0]), filename)
credit to someone online whose name I don't remember.. (sorry it's late and I'm exhausted!)
Then, if you're using PyInstaller2.0, in cmd, from the pyinstaller-2.0 dir, you can run
pyinstaller.py --onefile myscriptsname.py
That will create a myscriptsname.spec file in the pyinstaller-2.0 dir. It will also create an exe, but that won't work. It will be updated later. Now edit that .spec, and add the following a.datas line (remember datas, not data). I included a little extra in the .spec file just for reference.
a = Analysis(['ServerTimeTest_nograph.py'],
pathex=['c:\\Python27\\pyinstaller-2.0'],
hiddenimports=[],
hookspath=None)
a.datas += [('myfilesname.type','C:\\path\\to\\my\\file\\myfilesname.type','DATA')]
pyz = PYZ(a.pure)
Now, back in cmd, run
pyinstaller.py --onefile myscriptsname.spec
This will update your .exe in the /dist dir.
Maybe there's a better way, or a prettier way, but this worked for me!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With