py2exe/py2app and docx don't work together - python
Installed docx on Windows 7 here:
D:\Program Files (x86)\Python27\Lib\site-packages as shown below:
Installed docx on OS X at /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/docx-0.0.2-py2.7.egg-info as shown below:
Following is the sample script (named as docx_example.py), which runs absolutely fine on the python interpreter:
#!/usr/bin/env python
'''
This file makes an docx (Office 2007) file from scratch, showing off most of python-docx's features.
If you need to make documents from scratch, use this file as a basis for your work.
Part of Python's docx module - http://github.com/mikemaccana/python-docx
See LICENSE for licensing information.
'''
from docx import *
if __name__ == '__main__':
# Default set of relationshipships - these are the minimum components of a document
relationships = relationshiplist()
# Make a new document tree - this is the main part of a Word document
document = newdocument()
# This xpath location is where most interesting content lives
docbody = document.xpath('/w:document/w:body', namespaces=nsprefixes)[0]
# Append two headings and a paragraph
docbody.append(heading('''Welcome to Python's docx module''',1) )
docbody.append(heading('Make and edit docx in 200 lines of pure Python',2))
docbody.append(paragraph('The module was created when I was looking for a Python support for MS Word .doc files on PyPI and Stackoverflow. Unfortunately, the only solutions I could find used:'))
# Add a numbered list
for point in ['''COM automation''','''.net or Java''','''Automating OpenOffice or MS Office''']:
docbody.append(paragraph(point,style='ListNumber'))
docbody.append(paragraph('''For those of us who prefer something simpler, I made docx.'''))
docbody.append(heading('Making documents',2))
docbody.append(paragraph('''The docx module has the following features:'''))
# Add some bullets
for point in ['Paragraphs','Bullets','Numbered lists','Multiple levels of headings','Tables','Document Properties']:
docbody.append(paragraph(point,style='ListBullet'))
docbody.append(paragraph('Tables are just lists of lists, like this:'))
# Append a table
docbody.append(table([['A1','A2','A3'],['B1','B2','B3'],['C1','C2','C3']]))
docbody.append(heading('Editing documents',2))
docbody.append(paragraph('Thanks to the awesomeness of the lxml module, we can:'))
for point in ['Search and replace','Extract plain text of document','Add and delete items anywhere within the document']:
docbody.append(paragraph(point,style='ListBullet'))
# Search and replace
print 'Searching for something in a paragraph ...',
if search(docbody, 'the awesomeness'): print 'found it!'
else: print 'nope.'
print 'Searching for something in a heading ...',
if search(docbody, '200 lines'): print 'found it!'
else: print 'nope.'
print 'Replacing ...',
docbody = replace(docbody,'the awesomeness','the goshdarned awesomeness')
print 'done.'
# Add a pagebreak
docbody.append(pagebreak(type='page', orient='portrait'))
docbody.append(heading('Ideas? Questions? Want to contribute?',2))
docbody.append(paragraph('''Email <python.docx#librelist.com>'''))
# Create our properties, contenttypes, and other support files
coreprops = coreproperties(title='Python docx demo',subject='A practical example of making docx from Python',creator='Mike MacCana',keywords=['python','Office Open XML','Word'])
appprops = appproperties()
contenttypes = contenttypes()
websettings = websettings()
wordrelationships = wordrelationships(relationships)
# Save our document
savedocx(document,coreprops,appprops,contenttypes,websettings,wordrelationships,'docx_example.docx')
Following is the setup script (named as docx_setup.py) to create the standalone (.app in Mac OSX and .exe in Windows 7):
import sys,os
# Globals: START
main_script='docx_example'
dist_dir_main_path=os.path.abspath('./docx-bin')
compression_level=2
optimization_level=2
bundle_parameter=1
skip_archive_parameter=False
emulation_parameter=False
module_cross_reference_parameter=False
ascii_parameter=False
includes_list=['lxml.etree','lxml._elementpath','gzip']
# Globals: STOP
# Global Functions: START
def isDarwin():
return sys.platform=='darwin'
def isLinux():
return sys.platform=='linux2'
def isWindows():
return os.name=='nt'
# Global Functions: STOP
if isDarwin():
from setuptools import setup
# Setup distribution directory: START
dist_dir=os.path.abspath('%s/osx' %(dist_dir_main_path))
if os.path.exists(dist_dir):
os.system('rm -rf %s' %(dist_dir))
os.system('mkdir -p %s' %(dist_dir))
# Setup distribution directory: STOP
APP = ['%s.py' %(main_script)]
OPTIONS={'argv_emulation': False,
'dist_dir': dist_dir,
'includes': includes_list
}
print 'Creating standalone now...'
setup(app=APP,options={'py2app': OPTIONS},setup_requires=['py2app'])
os.system('rm -rf build')
os.system('tar -C %s -czf %s/%s.tgz %s.app' %(dist_dir,dist_dir,main_script,main_script))
os.system('rm -rf %s/%s.app' %(dist_dir,main_script))
print 'Re-distributable Standalone file(s) created at %s/%s.zip. Unzip and start using!!!' %(dist_dir,main_script)
elif isWindows():
from distutils.core import setup
import py2exe
# Setup distribution directory: START
dist_dir=os.path.abspath('%s/win' %(dist_dir_main_path))
if os.path.exists(dist_dir):
os.system('rmdir /S /Q %s' %(dist_dir))
os.system('mkdir %s' %(dist_dir))
# Setup distribution directory: STOP
OPTIONS={'compressed': compression_level,
'optimize': optimization_level,
'bundle_files': bundle_parameter,
'dist_dir': dist_dir,
'xref': module_cross_reference_parameter,
'skip_archive': skip_archive_parameter,
'ascii': ascii_parameter,
'custom_boot_script': '',
'includes': includes_list
}
print 'Creating standalone now...'
setup(options = {'py2exe': OPTIONS},zipfile = None,windows=[{'script': '%s.py' %(main_script)}])
print 'Re-distributable Standalone file(s) created in the following location: %s' %(dist_dir)
os.system('rmdir /S /Q build')
Now comes the real problem.
Following is the error posted on Mac OS X console after trying to use the docx_example.app, created using the command python docx_setup.py py2app:
docx_example: Searching for something in a paragraph ... found it!
docx_example: Searching for something in a heading ... found it!
docx_example: Replacing ... done.
docx_example: Traceback (most recent call last):
docx_example: File "/Users/admin/docx-bin/osx/docx_example.app/Contents/Resources/__boot__.py", line 64, in <module>
docx_example: _run('docx_example.py')
docx_example: File "/Users/admin/docx-bin/osx/docx_example.app/Contents/Resources/__boot__.py", line 36, in _run
docx_example: execfile(path, globals(), globals())
docx_example: File "/Users/admin/docx-bin/osx/docx_example.app/Contents/Resources/docx_example.py", line 75, in <module>
docx_example: savedocx(document,coreprops,appprops,contenttypes,websettings,wordrelationships,'docx_example.docx')
docx_example: File "docx.pyc", line 849, in savedocx
docx_example: AssertionError
docx_example: docx_example Error
docx_example Exited with code: 255
Following is the error posted in docx_example.exe.log file in Windows 7 after trying to use the docx_example.exe, created using the command python docx_setup.py py2exe:
Traceback (most recent call last):
File "docx_example.py", line 75, in <module>
File "docx.pyo", line 854, in savedocx
WindowsError: [Error 3] The system cannot find the path specified: 'D:\\docx_example\\docx_example.exe\\template'
As you can see, both OS X and Windows 7 are referring to something similar here. Please help.
i have found a solution
in api.py
From
_thisdir = os.path.split(__file__)[0]
To
_thisdir = 'C:\Python27\Lib\site-packages\docx'
Or whatever your docx file is
What's going on (at least for py2exe) is something similar to this question.
The documentation on data_files is here.
What you basically have to do is change
setup(options = {'py2exe': OPTIONS},zipfile = None,windows=[{'script': '%s.py' %(main_script)}])
to
data_files = [
('template', 'D:/Program Files (x86)/Python27/Lib/site-packages/docx-template/*'),
]
setup(
options={'py2exe': OPTIONS},
zipfile=None,
windows=[{'script': '%s.py' %(main_script)}],
data_files=data_files
)
The exact place where the template files are may be wrong above, so you might need to adjust it.
But there may be several other sets of data_files you need to include. You may want to go about retrieving them programatically with an os.listdir or os.walk type of command.
As mentioned in the other post, you will also have to change
bundle_parameter=1
to
bundle_parameter=2
at the top of the file.
You can solve the entire problem by using this API which is based in python-docx. The advantage of the API is that this one doesnt have the savedoc function so you will not have any other AssertionError.
For the WindowsError: [Error 3] The system cannot find the path specified: 'D:\\docx_example\\docx_example.exe\\template' error you need to edit the api.py file of docx egg folder which is located in the Python folder of the system (in my computer: C:\Python27\Lib\site-packages\python_docx-0.3.0a5-py2.7.egg\docx)
Changing this:
_thisdir = os.path.split(__file__)[0]
_default_docx_path = os.path.join(_thisdir, 'templates', 'default.docx')
To this:
thisdir = os.getcwd()
_default_docx_path = os.path.join(thisdir, 'templates', 'default.docx')
The first one was taking the actual running program and adding it to the path to locate the templates folder.
C:\myfiles\myprogram.exe\templates\default.docx
The solution takes only the path, not the running program.
C:\myfiles\templates\default.docx
Hope it helps!
Instead of changing some library file, I find it easier and cleaner to tell python-docx explicitly where to look for the template, i.e.:
document = Document('whatever/path/you/choose/to/some.docx')
This effectively solves the py2exe and docx path problem.
Related
Python erronously adding file extension to path string
I'm currently struggling with the following problem: My folder structer looks like: master - resources customFile.fmu fileCallingFMU.py While executing the fileCallingFMU.py I pass a path string like path = "./resources/customFile.fmu" My script contains a super function where I pass the path variable. But everytime I execute the script it trips with an exception: Exception has occurred: FileNotFoundError [Errno 2] No such file or directory: b'2021-11-16_./resources/customFile.fmu.txt' File "[projectFolder]\fileCallingFMU.py", line 219, in __init__ super().__init__(path, config, log_level) File "[projectFolder]\fileCallingFMU.py", line 86, in <module> env = gym.make(env_name) My urging question now is the following: Why and how does python manipulate the path variable with a date-prefix and .txt as file extension?! Hope anyone can enlighten me on this one... EDIT I'm trying to get the example of ModelicaGym running. My fileCallingFMU.py contains the following code: path = "./resources/customFile.fmu" env_entry_point = 'cart_pole_env:JModelicaCSCartPoleEnv' config = { 'path': path, 'm_cart': m_cart, 'm_pole': m_pole, 'theta_0': theta_0, 'theta_dot_0': theta_dot_0, 'time_step': time_step, 'positive_reward': positive_reward, 'negative_reward': negative_reward, 'force': force, 'log_level': log_level } from gym.envs.registration import register env_name = env_name register( id=env_name, entry_point=env_entry_point, kwargs=config ) env = gym.make(env_name) The full code for the entryPoint can be found here.
As jjramsey pointed out the problem was burried within the ModelicaGym library. The logger could not create a propper log file, because the model name was not properly stored in the self.model variable. Source of this error lied in the line self.model_name = model_path.split(os.path.sep)[-1] due to the fact that the os library was not able to separate my path string "./resources/customFile.fmu" After changing it to ".\\resources\\customFile.fmu" everythig works as expected. Thanks again!
P4Python run method does not work on empty folder
I want to search a Perforce depot for files. I do this from a python script and use the p4python library command: list = p4.run("files", "//mypath/myfolder/*") This works fine as long as myfolder contains some files. I get a python list as a return value. But when there is no file in myfolder the program stops running and no error message is displayed. My goal is to get an empty python list, so that I can see that this folder doesn't contain any files. Does anybody has some ideas? I could not find information in the p4 files documentation and on StackOverflow.
I'm going to guess you've got an exception handler around that command execution that's eating the exception and exiting. I wrote a very simple test script and got this: C:\Perforce\test>C:\users\samwise\AppData\local\programs\python\Python36-32\python files.py Traceback (most recent call last): File "files.py", line 6, in <module> print(p4.run("files", "//depot/no such path/*")) File "C:\users\samwise\AppData\local\programs\python\Python36-32\lib\site-packages\P4.py", line 611, in run raise e File "C:\users\samwise\AppData\local\programs\python\Python36-32\lib\site-packages\P4.py", line 605, in run result = P4API.P4Adapter.run(self, *flatArgs) P4.P4Exception: [P4#run] Errors during command execution( "p4 files //depot/no such path/*" ) [Error]: "//depot/no such path/* - must refer to client 'Samwise-dvcs-1509687817'."
Try something like this ? import os if len(os.listdir('//mypath/myfolder/') ) == 0: # Do not execute p4.run if directory is empty list = [] else: list = p4.run("files", "//mypath/myfolder/*")
Can't create user site-packages directory for usercustomize.py file
I need to add the win_unicode_console module to my usercustomize.py file, as described by the documentation. I've discovered my user site packages directory with: >>> import site >>> site.getusersitepackages() 'C:\\Users\\my name\\AppData\\Roaming\\Python\\Python35\\site-packages' I haven't been able to get to this directory using any method. I've tried using pushd instead of cd to emulate a network drive, and I've also tried getting there using run. No matter what I do in python, or in cmd terminal. I get the response The network path was not found. Here is an example of one I've tried in cmd: C:\>pushd \\Users\\my name\\AppData\\Roaming\\Python\\Python35\\site-packages The network path was not found. What am I doing wrong, or what could be wrong with the path?
DOS style backslashes don't need to be escaped within the Windows console (else they may have used forward slashes way back when!). Follow these steps to manually create usercustomize.py: Start->Run:cmd Make sure you're on the C: drive c: Create the directory. mkdir creates the missing parents. Obviously, change "my name" as appropriate. mkdir C:\Users\my name\AppData\Roaming\Python\Python35\site-packages Create usercustomize.py: notepad C:\Users\my name\AppData\Roaming\Python\Python35\site-packages\usercustomize.py Click "yes" to create your file. Edit as appropriate Or use the following script to have Python do it for you: import site import os import os.path import io user_site_dir = site.getusersitepackages() user_customize_filename = os.path.join(user_site_dir, 'usercustomize.py') win_unicode_console_text = u""" # win_unicode_console import win_unicode_console win_unicode_console.enable() """ if os.path.exists(user_site_dir): print("User site dir already exists") else: print("Creating site dir") os.makedirs(user_site_dir) if not os.path.exists(user_customize_filename): print("Creating {filename}".format(filename=user_customize_filename)) file_mode = 'w+t' else: print("{filename} already exists".format(filename=user_customize_filename)) file_mode = 'r+t' with io.open(user_customize_filename, file_mode) as user_customize_file: existing_text = user_customize_file.read() if not win_unicode_console_text in existing_text: # file pointer should already be at the end of the file after read() user_customize_file.write(win_unicode_console_text) print("win_unicode_console added to {filename}".format(filename=user_customize_filename)) else: print("win_unicode_console already enabled")
how to access SHOpenFolderAndSelectItems() by ctypes
I want to build a cross-platform application ,I used a windows API called SHOpenFolderAndSelectItems(). Although I found example called it by pywin32,but pywin32 is not available on Linux , I don't want to call a Windows API on linux,just don't want to make another code version for Linux,so I wonder how to access it by ctypes? yes,this API cannot be called on Linux ,I just want to make it silent in the code so that I can freeze the Python scripts into executables by cx_Freeze without pywin32 module-missing error happend . from win32com.shell import shell, shellcon import os def launch_file_explorer(path, files): ''' Given a absolute base path and names of its children (no path), open up one File Explorer window with all the child files selected ''' folder_pidl = shell.SHILCreateFromPath(path,0)[0] desktop = shell.SHGetDesktopFolder() shell_folder = desktop.BindToObject(folder_pidl, None,shell.IID_IShellFolder) name_to_item_mapping = dict([(desktop.GetDisplayNameOf(item, shellcon.SHGDN_FORPARSING|shellcon.SHGDN_INFOLDER), item) for item in shell_folder]) print(name_to_item_mapping) to_show = [] for file in files: if file in name_to_item_mapping: to_show.append(name_to_item_mapping[file]) # else: # raise Exception('File: "%s" not found in "%s"' % (file, path)) shell.SHOpenFolderAndSelectItems(folder_pidl, to_show, 0) p=r'E:\aa' print(os.listdir(p)) launch_file_explorer(p, os.listdir(p))
How do I use cx_freeze?
I've created my setup.py file as instructed but I don't actually.. understand what to do next. Typing "python setup.py build" into the command line just gets a syntax error. So, what do I do? setup.py: from cx_Freeze import setup, Executable setup( name = "On Dijkstra's Algorithm", version = "3.1", description = "A Dijkstra's Algorithm help tool.", exectuables = [Executable(script = "Main.py", base = "Win32GUI")])
Add import sys as the new topline You misspelled "executables" on the last line. Remove script = on last line. The code should now look like: import sys from cx_Freeze import setup, Executable setup( name = "On Dijkstra's Algorithm", version = "3.1", description = "A Dijkstra's Algorithm help tool.", executables = [Executable("Main.py", base = "Win32GUI")]) Use the command prompt (cmd) to run python setup.py build. (Run this command from the folder containing setup.py.) Notice the build parameter we added at the end of the script call.
I'm really not sure what you're doing to get that error, it looks like you're trying to run cx_Freeze on its own, without arguments. So here is a short step-by-step guide on how to do it in windows (Your screenshot looks rather like the windows command line, so I'm assuming that's your platform) Write your setup.py file. Your script above looks correct so it should work, assuming that your script exists. Open the command line (Start -> Run -> "cmd") Go to the location of your setup.py file and run python setup.py build Notes: There may be a problem with the name of your script. "Main.py" contains upper case letters, which might cause confusion since windows' file names are not case sensitive, but python is. My approach is to always use lower case for scripts to avoid any conflicts. Make sure that python is on your PATH (read http://docs.python.org/using/windows.html)1 Make sure are are looking at the new cx_Freeze documentation. Google often seems to bring up the old docs.
I ran into a similar issue. I solved it by setting the Executable options in a variable and then simply calling the variable. Below is a sample setup.py that I use: from cx_Freeze import setup, Executable import sys productName = "ProductName" if 'bdist_msi' in sys.argv: sys.argv += ['--initial-target-dir', 'C:\InstallDir\\' + productName] sys.argv += ['--install-script', 'install.py'] exe = Executable( script="main.py", base="Win32GUI", targetName="Product.exe" ) setup( name="Product.exe", version="1.0", author="Me", description="Copyright 2012", executables=[exe], scripts=[ 'install.py' ] )
You can change the setup.py code to this: from cx_freeze import setup, Executable setup( name = "foo", version = "1.1", description = "Description of the app here.", executables = [Executable("foo.py")] ) I am sure it will work. I have tried it on both windows 7 as well as ubuntu 12.04
find the cxfreeze script and run it. It will be in the same path as your other python helper scripts, such as pip. cxfreeze Main.py --target-dir dist read more at: http://cx-freeze.readthedocs.org/en/latest/script.html#script
I usually put the calling setup.py command into .bat file to easy recall. Here is simple code in COMPILE.BAT file: python setup.py build #ECHO: #ECHO . : ` . * F I N I S H E D * . ` : . #ECHO: #Pause And the setup.py is organized to easy customizable parameters that let you set icon, add importe module library: APP_NAME = "Meme Studio"; ## < Your App's name Python_File = "app.py"; ## < Main Python file to run Icon_Path = "./res/iconApp48.ico"; ## < Icon UseFile = ["LANGUAGE.TXT","THEME.TXT"]; UseAllFolder = True; ## Auto scan folder which is same level with Python_File and append to UseFile. Import = ["infi","time","webbrowser", "cv2","numpy","PIL","tkinter","math","random","datetime","threading","pathlib","os","sys"]; ## < Your Imported modules (cv2,numpy,PIL,...) Import+=["pkg_resources","xml","email","urllib","ctypes", "json","logging"] ################################### CX_FREEZE IGNITER ################################### from os import walk def dirFolder(folderPath="./"): return next(walk(folderPath), (None, None, []))[1]; # [ Folder ] def dirFile(folderPath="./"): return next(walk(folderPath), (None, None, []))[2]; # [ File ] if UseAllFolder: UseFile += dirFolder(); import sys, pkgutil; from cx_Freeze import setup, Executable; BasicPackages=["collections","encodings","importlib"] + Import; def AllPackage(): return [i.name for i in list(pkgutil.iter_modules()) if i.ispkg]; # Return name of all package #Z=AllPackage();Z.sort();print(Z); #while True:pass; def notFound(A,v): # Check if v outside A try: A.index(v); return False; except: return True; build_msi_options = { 'add_to_path': False, "upgrade_code": "{22a35bac-14af-4159-7e77-3afcc7e2ad2c}", "target_name": APP_NAME, "install_icon": Icon_Path, 'initial_target_dir': r'[ProgramFilesFolder]\%s\%s' % ("Picox", APP_NAME) } build_exe_options = { "includes": BasicPackages, "excludes": [i for i in AllPackage() if notFound(BasicPackages,i)], "include_files":UseFile, "zip_include_packages": ["encodings"] ## } setup( name = APP_NAME, options = {"build_exe": build_exe_options},#"bdist_msi": build_msi_options},#, executables = [Executable( Python_File, base='Win32GUI',#Win64GUI icon=Icon_Path, targetName=APP_NAME, copyright="Copyright (C) 2900AD Muc", )] ); The modules library list in the code above is minimum for workable opencv + pillow + win32 application. Example of my project file organize: ========== U P D A T E ========== Although cx_Freeze is a good way to create setup file. It's really consume disk space if you build multiple different software project that use large library module like opencv, torch, ai... Sometimes, users download installer, and receive false positive virus alert about your .exe file after install. Thus, you should consider use SFX archive (.exe) your app package and SFX python package separate to share between app project instead. You can create .bat that launch .py file and then convert .bat file to .exe with microsoft IExpress.exe. Next, you can change .exe icon to your own icon with Resource Hacker: http://www.angusj.com/resourcehacker/ And then, create SFX archive of your package with PeaZip: https://peazip.github.io/ Finally change the icon. The Python Package can be pack to .exe and the PATH register can made with .bat that also convertable to .exe. If you learn more about command in .bat file and make experiments with Resource Hacker & self extract ARC in PeaZip & IExpress, you can group both your app project, python package into one .exe file only. It'll auto install what it need on user machine. Although this way more complex and harder, but then you can custom many install experiences included create desktop shorcut, and install UI, and add to app & feature list, and uninstall ability, and portable app, and serial key require, and custom license agreement, and fast window run box, and many more,..... but the important features you get is non virus false positive block, reduce 200MB to many GB when user install many your python graphic applications.