pyinstaller stops python from reading from script directory - python-3.x

I have this block of code that works in python script form but when I package the script to an exe using pyinstaller it always results in the program saying the config file can't be found. I put the config.ini in the same folder as the exe file.
config = configparser.ConfigParser()
configComplete = True
configExists = False
try:
open(os.path.join(sys.path[0],'config.ini'))
config.read(os.path.join(sys.path[0],'config.ini'))
destination = config['server']['ServerAddress']
key = config['server']['ApiKey']
configExists = True
except KeyError:
configComplete = False
except FileNotFoundError:
try:
open(expanduser('~/.config/octoprint-cli.ini'))
config.read(expanduser('~/.config/octoprint-cli.ini'))
destination = config['server']['ServerAddress']
key = config['server']['ApiKey']
configExists = True
except KeyError:
configComplete = False
except FileNotFoundError:
pass

I don't have python currently installed to test this on my machine, but typically when I am looking for a file that's relative to the python file location it's preferable to use:
import os
CONFIG_FILE_PATH = f"{os.path.dirname(__file__)}{os.sep}config.ini"
if os.path.exists(CONFIG_FILE_PATH): # If the file already exists
config.read(CONFIG_FILE_PATH) # Read it
else: # If a config file does not exist
# Either throw error or create fresh config
This code is an OS agnostic way of looking for a file in the same directory as the python file and the catching doesn't necessarily throw an error unless you want it to.
See if that works with pyinstaller, as I believe when I last used it this worked.

Related

Getting FileNotFoundError when calling python coded file from robot framework

I am trying to write an automation code for picking up different environment values for execution of my testcases based on the value I pass for environment.
Here is the code I tried :
# env.robot
*** Settings ***
Variables setup.py stage01
*** Test Cases ***
Print values
log to console ${data}
# setup.py
from robot.libraries.BuiltIn import BuiltIn
import xlrd
def get_variables(env):
file_location = "values.xlsx"
workbook = xlrd.open_workbook(file_location)
sheet = workbook.sheet_by_name(env)
print("Env : " + sheet.name)
data = [[sheet.cell_value(r, c) for c in range(sheet.ncols)] for r in range(sheet.nrows)]
print(data)
BuiltIn().log_to_console(data)
return data
Response I am getting :
[ ERROR ] Error in file 'D:\env.robot': Processing variable file 'D:\setup2.py' with arguments [ stage01 ]
failed: FileNotFoundError: [Errno 2] No such file or directory: 'values.xlsx'
values.xlsx is present in the same directory with .py and .robot file
I want to get the data from values.xlsx file based on the value of env variable and use the values in robot testcases.
Please suggest what I need to modify or any other approach would also do.

sorting error :"already exist"

This code was suppose tu sort my desktop , path =/Users/nicolas/Desktop/prova/
and it works properly if the destination folder doesnt exist and the program create it ,
else if there is already a folder with the same name it give an error when he tries to move the files and it says
complete output:
.DS_Store
nltks
png
Scherm.png
Schermata 2018-03-28 alle 11.07.13.png
DS_Store
nltks
png
png
Traceback (most recent call last):
File "/Users/nicolas/Desktop/tts/work in progress/sorting machine.py", line 16, in
shutil.move(path+names[x],path+currentexp)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/shutil.py", line 292, in move
raise Error, "Destination path '%s' already exists" % real_dst
shutil.Error: Destination path '/Users/nicolas/Desktop/prova/png/Scherm.png' already exists
iMac:w
but i ve not any file in it with the ds_store estension and the "nltk" is just a folder that shouldnt move .
program
import os
import shutil
path = "/Users/nicolas/Desktop/prova/"
names = os.listdir(path)
for x in range (0,len(names)):
print names[x]
for x in range (0,len(names)):
exp = names[x].split(".")
currentexp = exp[-1]
print (currentexp)
if os.path.exists(path+currentexp):
shutil.move(os.path.join(path, names[x]), os.path.join(path,currentexp))
else:
os.makedirs(path+currentexp)
shutil.move(os.path.join(path, names[x]), os.path.join(path,currentexp))
# if names[x] not in os.path.exists(path+currentexp):
# shutil.move(path+names[x],path+curentexp)
thanks for the help
from the documentation:
If the destination is an existing directory, then src is moved inside that directory. If the destination already exists but is not a directory, it may be overwritten depending on os.rename() semantics
To sum it up, if the image exists in the target dir, and both source & target dirs are on the same filesystem, shutil.move can use os.rename, and os.rename fails because you cannot rename an object with the name of an already existing one. You have to delete the target first.
Here's how I'd rewrite it:
target_dir = os.path.join(path,currentexp)
if not os.path.exists(target_dir):
os.makedirs(target_dir)
try:
os.remove(os.path.join(target_dir, names[x]))
except OSError:
pass # cannot remove or doesn't exist, ignore
shutil.move(os.path.join(path, names[x]), target_dir)
this simpler code tries to delete the target file before performing shutil.move. Of course os.remove can fail, failure is trapped, then shutil.move fails because of another error, but that's beyond our scope

How to get the default application mapped to a file extention in windows using Python

I would like to query Windows using a file extension as a parameter (e.g. ".jpg") and be returned the path of whatever app windows has configured as the default application for this file type.
Ideally the solution would look something like this:
from stackoverflow import get_default_windows_app
default_app = get_default_windows_app(".jpg")
print(default_app)
"c:\path\to\default\application\application.exe"
I have been investigating the winreg builtin library which holds the registry infomation for windows but I'm having trouble understanding its structure and the documentation is quite complex.
I'm running Windows 10 and Python 3.6.
Does anyone have any ideas to help?
The registry isn't a simple well-structured database. The Windows
shell executor has some pretty complex logic to it. But for the simple cases, this should do the trick:
import shlex
import winreg
def get_default_windows_app(suffix):
class_root = winreg.QueryValue(winreg.HKEY_CLASSES_ROOT, suffix)
with winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, r'{}\shell\open\command'.format(class_root)) as key:
command = winreg.QueryValueEx(key, '')[0]
return shlex.split(command)[0]
>>> get_default_windows_app('.pptx')
'C:\\Program Files\\Microsoft Office 15\\Root\\Office15\\POWERPNT.EXE'
Though some error handling should definitely be added too.
Added some improvements to the nice code by Hetzroni, in order to handle more cases:
import os
import shlex
import winreg
def get_default_windows_app(ext):
try: # UserChoice\ProgId lookup initial
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\{}\UserChoice'.format(ext)) as key:
progid = winreg.QueryValueEx(key, 'ProgId')[0]
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'SOFTWARE\Classes\{}\shell\open\command'.format(progid)) as key:
path = winreg.QueryValueEx(key, '')[0]
except: # UserChoice\ProgId not found
try:
class_root = winreg.QueryValue(winreg.HKEY_CLASSES_ROOT, ext)
if not class_root: # No reference from ext
class_root = ext # Try direct lookup from ext
with winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, r'{}\shell\open\command'.format(class_root)) as key:
path = winreg.QueryValueEx(key, '')[0]
except: # Ext not found
path = None
# Path clean up, if any
if path: # Path found
path = os.path.expandvars(path) # Expand env vars, e.g. %SystemRoot% for ext .txt
path = shlex.split(path, posix=False)[0] # posix False for Windows operation
path = path.strip('"') # Strip quotes
# Return
return path

Python 3.3:cx_freeze & pyserial: cannot import traceback module

I'm newbie in cx_freeze. I'm triing to make an executable from python 3.3 script that uses "time", "serial" and "tkinter".
Cx_freeze run without any errors, but starting the exe file is resulting with error:
cannot import traceback module
Exception: No module named 're'
Original Exception: No module named 'serial'
I have this setup.py of cx_freeze
from cx_Freeze import setup, Executable
includes = ["serial", "tkinter"]
excludes = []
packages = []
path = []
GUI2Exe_Target_1 = Executable(
# what to build
script ='test6.1.py',
initScript = None,
base = 'Win32GUI',
targetDir = r"dist",
targetName = "bludiste2.exe",
compress = True,
copyDependentFiles = True,
appendScriptToExe = False,
appendScriptToLibrary = False,
icon = None
)
Does anyone know, how to solve it, please?
Thank you.
The first two lines are a bug that will be fixed in the next version of cx_Freeze. If you stick an import re in your script, you'll see the correct error message.
The last line is your real problem - that means it didn't find the serial module when you froze it. Check where pyserial is installed on your computer.

How to create a symbolic link with SCons?

I'm using SCons for building a project and need to add a symbolic link to a file it is installing via env.Install. What command(s) will make a link that's the equivalent of running ln -s on the command line?
SCons doesn't have a dedicated symbolic link command, but you can use os.symlink(src, dst) from Python's os module:
import os
env = Environment()
def SymLink(target, source, env):
os.symlink(os.path.abspath(str(source[0])), os.path.abspath(str(target[0])))
env.Command("file.out", "file.in", SymLink)
This may not work correctly on Windows, I've only tried it on Linux.
There seems to be little advancement in the SCons core code for symbolic link support and I wasn't satisfied any one solution I found on the web. Here is a potential builder which incorporates aspects of both Nick's and richq's answers. Additionally, it will catch name changes (due to the emitter method) and is as platform-agnostic as I could get it.
I prefer this builder because it will make links relative to the directory in which they are installed. One could add an option to force the link to be absolute I suppose, but I have not needed or wanted that yet.
Currently, if the OS doesn't support symlinks, I just pass and do nothing, but one could use os.copytree() for example however the dependency becomes messy if the source is a directory so the emitter would need to do something fancy. I'm up for any suggestions here.
One can put the following code into the file site_scons/site_tools/symlink.py (with blank _init_.py files in the appropriate places). Then do this in the SConstruct file:
SConstruct:
env = Environment()
env.Tool('symlink')
env.SymLink('link_name.txt', 'real_file.txt')
symlink.py:
import os
from os import path
from SCons.Node import FS
from SCons.Script import Action, Builder
def generate(env):
'''
SymLink(link_name,source)
env.SymLink(link_name,source)
Makes a symbolic link named "link_name" that points to the
real file or directory "source". The link produced is always
relative.
'''
bldr = Builder(action = Action(symlink_builder,symlink_print),
target_factory = FS.File,
source_factory = FS.Entry,
single_target = True,
single_source = True,
emitter = symlink_emitter)
env.Append(BUILDERS = {'SymLink' : bldr})
def exists(env):
'''
we could test if the OS supports symlinks here, or we could
use copytree as an alternative in the builder.
'''
return True
def symlink_print(target, source, env):
lnk = path.basename(target[0].abspath)
src = path.basename(source[0].abspath)
return 'Link: '+lnk+' points to '+src
def symlink_emitter(target, source, env):
'''
This emitter removes the link if the source file name has changed
since scons does not seem to catch this case.
'''
lnk = target[0].abspath
src = source[0].abspath
lnkdir,lnkname = path.split(lnk)
srcrel = path.relpath(src,lnkdir)
if int(env.get('verbose',0)) > 3:
ldir = path.relpath(lnkdir,env.Dir('#').abspath)
if rellnkdir[:2] == '..':
ldir = path.abspath(ldir)
print ' symbolic link in directory: %s' % ldir
print ' %s -> %s' % (lnkname,srcrel)
try:
if path.exists(lnk):
if os.readlink(lnk) != srcrel:
os.remove(lnk)
except AttributeError:
# no symlink available, so we remove the whole tree? (or pass)
#os.rmtree(lnk)
print 'no os.symlink capability on this system?'
return (target, source)
def symlink_builder(target, source, env):
lnk = target[0].abspath
src = source[0].abspath
lnkdir,lnkname = path.split(lnk)
srcrel = path.relpath(src,lnkdir)
if int(env.get('verbose',0)) > 4:
print 'target:', target
print 'source:', source
print 'lnk:', lnk
print 'src:', src
print 'lnkdir,lnkname:', lnkdir, lnkname
print 'srcrel:', srcrel
if int(env.get('verbose',0)) > 4:
print 'in directory: %s' % path.relpath(lnkdir,env.Dir('#').abspath)
print ' symlink: %s -> %s' % (lnkname,srcrel)
try:
os.symlink(srcrel,lnk)
except AttributeError:
# no symlink available, so we make a (deep) copy? (or pass)
#os.copytree(srcrel,lnk)
print 'no os.symlink capability on this system?'
return None
This creates a builder to perform the job:
mylib = env.SharedLibrary("foobar", SRCS)
builder = Builder(action = "ln -s ${SOURCE.file} ${TARGET.file}", chdir = True)
env.Append(BUILDERS = {"Symlink" : builder})
mylib_link = env.Symlink("_foobar.so", mylib)
env.Default(mylib)
env.Default(mylib_link)
Again, this solution is for Linux.
If you wanted to issue the command directly to the shell and know the OS, subprocess can be used as well.
E.g.: subprocess.call(['ln', '-s', '</src/path>', '</dest/path>'])
In addition to Nicks solution, you can add a directory symlink by using a file as a directory name carrier. It's not the cleanest solution and debugging path names is a pain, but this works well:
def symlink_last(target_source_env):
src = os.path.basename(os.path.dirname(str(source[0])))
link = "deliverables/last"
print "Symlinking "+ src + "as" + link
os.symlink(src, link)
BUILD_TARGETS.append('link')
install_dir = "deliverables/subdir"
carrier_file = "filename"
builder = Builder(action = symlink_last, chdir=False)
env.Append(BUILDERS={ "Symlink" : builder })
env.Alias(target="link", source=env.Symlink(dir="deliverables", source = install_dir + carrier_file)
This will make a link to deliverables/subdir named deliverables/last, provided that a file deliverables/subdir/filename exists.

Resources