I have a python script that calls open an Excel file, calls a macro in the file, then closes. If I run the file from the CLI, it works. If i put it in Task Scheduler, I get an error from win32com.
Method opening the Excel file:
import win32com.client as WinCom
if os.path.exists(reportGeneratorFileName):
try:
xl = WinCom.Dispatch("Excel.Application")
xl.Workbooks.Open(Filename=os.path.abspath(reportGeneratorFileName))
xl.Application.Visible = False
xl.Application.Run("'{}'!Runner.Runner".format(reportGeneratorFileName))
l.info('Start Sleeping')
# Async mode of pythonw causes this to finish before the file is made
time.sleep(300)
l.info('Done Sleeping')
xl.Application.Quit()
except Exception as e:
l.error('Error updating file')
l.error(e, exc_info=True)
This is the Error i get:
06/04/2018 06:56:19 AM ERROR: (-2146959355, 'Server execution failed', None, None)
Traceback (most recent call last):
File "LAW Report.py", line 846, in createReport
xl = WinCom.Dispatch("Excel.Application")
File "c:\python27\lib\site-packages\win32com\client\__init__.py", line 95, in Dispatch
dispatch, userName = dynamic._GetGoodDispatchAndUserName(dispatch,userName,clsctx)
File "c:\python27\lib\site-packages\win32com\client\dynamic.py", line 114, in _GetGoodDispatchAndUserName
return (_GetGoodDispatch(IDispatch, clsctx), userName)
File "c:\python27\lib\site-packages\win32com\client\dynamic.py", line 91, in _GetGoodDispatch
IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx, pythoncom.IID_IDispatch)
com_error: (-2146959355, 'Server execution failed', None, None)
Now i am running 64 bit python 2.7 and 64 bit win32com while office is 32 bit, but as I said above, if I just run the script from the CLI it runs fine, just not from task manager. I am running this on a Windows Server 2012R2. I have tried configuring the task for 2008, 2008r2, and 2012r2. I also tried with highest privileges. I do need this to be able to run whether user is logged on or not. Everytime I have tested, the user has been logged on.
You need to
1) setup permissions in DCOMCnfg utility for user under which you're running -or-
2) change user to your desktop user account.
But first you need to get proper error code, not a generic message.
Pay attention that this should be considered as temporary solution since DCOM is badly supported by MS for automation as service. Consider switching to any library as soon as possible. There're numerous problems with Excel interop: you will have to reboot server from time to time, performance degradation with subsequent calls, you can't run Excels in parallel because of a good chance of errors, etc...
I encountered the same error of which my program can run from command prompt but not from task scheduler.
I solved this issue with these settings of task properties in task scheduler:
1. General->Security Options
a. make sure same user account you used to run python/microsoft program.
b. checked "Run only when user is logged on.
c. unchecked "Hidden"
For 1a, I'm using DOMAIN\userid that I used to login my laptop/PC.
This is the only way I found in order for the task scheduler to run successfully. Hope this helps.
Related
What I would like to do is be able to gain access to a computer over the network so I can create a new directory there that I will then save multiple files to throughout the rest of the script.
I have a script that creates a bunch of files that I need to save. The problem is that this script may be ran off any number of computers, but needs to save to the same computer. If I manually remote connect to the computer it prompts me for a username and password, but I am trying to just create a directory there. My code is below, along with the response I get.
if not os.path.exists(self.dirIn):
tryPath = self.dirIn.split("/")[0:-1]
tryPath = '/'.join(tryPath)
if not os.path.exists(tryPath):
os.mkdir(tryPath)
os.mkdir(str(self.dirIn))
else:
os.mkdir(str(self.dirIn))
WindowsError: [Error 1326] The user name or password is incorrect: '//computer/e$/directory/I/am/creating'
I am using Windows, Python27
I was able to just map the drive to my computer using subprocess, do what I needed, and then unmap the drive (optional)
subprocess.Popen("net use E: \\\\computername\\E$ %s /USER:%s" % (password, username))
time.sleep(1) # Short delay to allow E: drive to map before continuing
if not os.path.exists(self.dirIn):
os.makedirs(self.dirIn)
subprocess.Popen("net use E: /delete")
I did run into problems without the sleep, my program wouldn't find the directory without it.
Hope you can help me out, first question I ask myself but I am always impressed by the professional answers I find here!
I am using xlwings to both read and write data from .xls files. I am not a seasoned programmer, and I make mistakes. From time to time, this means rebooting processes, Python and what-not.
Every now and again, I would get the following AttributeError upon calling Workbook(). The real problem is not that I don't have a clue what is happening (I tried reading the modules the error diagnostics reference to, but they are written on a level of Python that is beyond my skills), but that restarting and even rebooting(!) my laptop don't (always) solve the problem.
I wish I could give some clues as to what is happening, but it appears to be a randomly occurring problem and right now, three reboots and several restarts didn't fix it. Google can't help either. I must have run my program a hundred times by now and it wasn't always a problem! The error message, upon simply calling Workbook():
wb = Workbook()
Traceback (most recent call last):
File "<ipython-input-22-4a3c36eb9bf9>", line 1, in <module>
wb = Workbook()
File "C:\Program Files\Anaconda\lib\site-packages\xlwings\main.py", line 141, in __init__
self.xl_app, self.xl_workbook = xlplatform.new_workbook()
File "C:\Program Files\Anaconda\lib\site-packages\xlwings\_xlwindows.py", line 104, in new_workbook
xl_app = _get_latest_app()
File "C:\Program Files\Anaconda\lib\site-packages\xlwings\_xlwindows.py", line 88, in _get_latest_app
return xl_workbook_current.Application
File "C:\Program Files\Anaconda\lib\site-packages\win32com\client\dynamic.py", line 522, in __getattr__
raise AttributeError("%s.%s" % (self._username_, attr))
AttributeError: Open.Application
And as a follow up, the piece of code from 'dyamic.py' raising the error:
[...]
# If we are still here, and have a retEntry, get the OLE item
if not retEntry is None:
invoke_type = _GetDescInvokeType(retEntry, pythoncom.INVOKE_PROPERTYGET)
debug_attr_print("Getting property Id 0x%x from OLE object" % retEntry.dispid)
try:
ret = self._oleobj_.Invoke(retEntry.dispid,0,invoke_type,1)
except pythoncom.com_error, details:
if details.hresult in ERRORS_BAD_CONTEXT:
# May be a method.
self._olerepr_.mapFuncs[attr] = retEntry
return self._make_method_(attr)
raise
debug_attr_print("OLE returned ", ret)
return self._get_good_object_(ret)
# no where else to look.
raise AttributeError("%s.%s" % (self._username_, attr))
As I mentioned before, the last bit it too much for me :P
I guessed some lingering Excel.exe (or similar) process was interfering with the script after I closed some random window due to some random error, but I cant find one in the task manager. Also, this is the kind of thing a reboot should fix, right?! I also upgraded to xlwings .34 (latest version, as of now).
Windows 8.1 64 bit, Python 2.7 (Anaconda distribution, Spyder IDE), Excel 2013.
Any help is very much appreciated, of course!
Thanks a lot, kind regards,
Gordon.
EDIT:
Following advice given in the comments, I can now report that even at times when wb = Workbook() fails, from win32com.client import dynamic followed by dynamic.Dispatch('Excel.Application') returns <COMObject Excel.Application>.
Hope it helps!
Always check either any issues to open the excel sheet, such as password protected/Licensed issues..
If there is any pop up coming while opening excel, you may get the same error.
on my Raspberry Pi, I encounter a strange behaviour regarding the use of the PiCamera module.
The following code runs smoothly when either started from IDLE (F5) or from the command prompt ($python test.py)
import picamera
if __name__ == "__main__":
camera=picamera.PiCamera()
camera.close()
But when I put the camera object into a class the code will run only when started from IDLE (F5):
import picamera
class VF:
def __init__(self):
self.camera = picamera.PiCamera()
def __del__(self):
self.camera.close()
if __name__ == "__main__":
myvf = VF()
When I start the above code from the command prompt, I get the following error message:
mmal: mmal_vc_component_enable: failed to enable component: ENOSPC
Traceback (most recent call last): File "test.py", line 14, in
myvf = VF()
File "test.py", line 6, in init
self.camera = picamera.PiCamera()
File "/usr/lib/python2.7/dist-packages/picamera/camera.py", line
379, in init
camera_num, self.STEREO_MODES[stereo_mode], stereo_decimate)
File "/usr/lib/python2.7/dist-packages/picamera/camera.py", line
505, in _init_camera
prefix="Camera component couldn't be enabled")
File "/usr/lib/python2.7/dist-packages/picamera/exc.py", line 133,
in mmal_check
raise PiCameraMMALError(status, prefix)
picamera.exc.PiCameraMMALError: Camera component couldn't be enabled:
Out of resources (other than memory)
The camera module is working correct, I just stripped the code down to the least possible size. Does anybody know this problem, or a similar problem, and can probably provide a solution? The Python Version is 2.7 and the Raspberry Rasbiab-System is completely up to date.
Thanks in advance.
I struggled with this one for hours, and kept getting the "out of resources" error. I finally figured out that in my take-the-picture function, I needed to make sure I did it like this:
camera = PiCamera()
(...camera settings here...)
camera.capture(myfileName)
camera.close()
If I didn't do the close(), I'd get that error every time.
So make sure that camera.close() is getting called right after the 'snap'. It solved the problem for me.
Found out, that the camera-module is not properly shut down when the destructor is not explicitly called (had LED turned off, so didn't see this).
IDLE handles a running camera by somehow resetting it before the script starts, but not the python interpreter.
So everything is ok now when the destructor is called before the script ends.
I'm using boto 2.5.1, Python 2.7, Ubuntu Precise. I want to mount a snapshot on an EC2 instance. I've gotten as far as creating a volume from the snapshot, but then I can't figure out how to attach it. If I do:
[setup stuff elided]
c = EC2Connection()
print volume
print instance
c.attach_volume(volume, instance, "/dev/snap")
I get the amazingly unhelpful exception:
vol-2df00677
i-1509d364
Traceback (most recent call last):
File "./mongo_pulldown.py", line 48, in <module>
main()
File "./mongo_pulldown.py", line 28, in main
c.attach_volume(volume, instance, "/dev/snap")
File "/home/roy/deploy/current/python/local/lib/python2.7/site-packages/boto/ec2/connection.py", line 1530, in attach_volume
return self.get_status('AttachVolume', params, verb='POST')
File "/home/roy/deploy/current/python/local/lib/python2.7/site-packages/boto/connection.py", line 985, in get_status
raise self.ResponseError(response.status, response.reason, body)
boto.exception.EC2ResponseError: EC2ResponseError: 400 Bad Request
with no clue of what I've done wrong. I'm assuming the device name is arbitrary, and the attach call will create the device as part of the process? Or does the device have the exist already?
How can I get some more useful diagnostic than just "Bad Request"?
The attach_volume method takes an instance_id and a volume_id but you are passing objects. Try this:
c.attach_volume(volume.id, instance.id, "/dev/sdh")
The device_name should be a reasonable device name for the OS you are using. You can find more about what that value should be here.
boto uses standard Python logging so you can configure it to log as much or as little as you want. This gist shows a shortcut approach to get full debug logging. However, boto can only log what it has access to and it's possible the response from EC2 just doesn't provide much information.
Well, it turns out that I was passing something bad for device. I was passing '/dev/snap'. When I changed that to 'xvdg', things worked. It appears that '/dev/xvdg' also works (and has the same effect; the '/dev/' part appears to be ignored).
I wrote a little function to find the next available unused device name:
def get_device_name():
for c in 'fghijklmnop':
name = "xvd%s" % c
path = "/dev/%s" % name
try:
os.stat(path)
except OSError:
return path
I was hoping that by using a fixed name outside of the set that's normally used, I could avoid having to worry about this silliness.
I have been having problems trying to run an external program from a python program that was generated from a trigger in a postgres 9.2 database. The trigger works. It writes to a file. I had tried just running the external program but the permissions would not allow it to run. I was able to create a folder (using os.system(“mkdir”) ). The owner of the folder is NETWORK SERVICE.
I need to run a program called sdktest. When I try to run it no response happens so I think that means that the python program does not have enough permissions (with an owner of NETWORK SERVICE) to run it.
I have been having my program copy files that it needs into that directory so they would have the correct permissions and that has worked to some degree but the program that I need to run is the last one and it is not running because it does not have enough permissions.
My python program runs a C++ program called PG_QB_Connector which calls sdktest.
Is there any way I can change the owner of the process to be a “normal” owner? Is there a better way to do this? Basically I just need to have this C++ program have eniough perms to run correctly.
BTW, when I run the C++ program by hand, the line that runs the sdktest program runs correctly, however, when I run it from the postgres/python it does not do anything...
I have Windows 7, python 3.2. The other 2 questions that I asked about this are located here and here
The python program:
CREATE or replace FUNCTION scalesmyone (thename text)
RETURNS int
AS $$
a=5
f = open('C:\\JUNK\\frompython.txt','w')
f.write(thename)
f.close()
import os
os.system('"mkdir C:\\TEMPWITHOWNER"')
os.system('"mkdir C:\\TEMPWITHOWNER\\addcustomer"')
os.system('"copy C:\\JUNK\\junk.txt C:\\TEMPWITHOWNER\\addcustomer"')
os.system('"copy C:\\BATfiles\\junk6.txt C:\\TEMPWITHOWNER\\addcustomer"')
os.system('"copy C:\\BATfiles\\run_addcust.bat C:\\TEMPWITHOWNER\\addcustomer"')
os.system('"copy C:\\Workfiles\\PG_QB_Connector.exe C:\\TEMPWITHOWNER\\addcustomer"')
os.system('"copy C:\\Workfiles\\sdktest.exe C:\\TEMPWITHOWNER\\addcustomer"')
import subprocess
return_code = subprocess.call(["C:\\TEMPWITHOWNER\\addcustomer\\PG_QB_Connector.exe", '"hello"'])
$$ LANGUAGE plpython3u;
The C++ program that is called from the python program and calls sdktest.exe is below
command = "copy C:\\Workfiles\\AddCustomerFROMWEB.xml C:\\TEMPWITHOWNER\\addcustomer\\AddCustomerFROMWEB.xml";
system(command.c_str());
//everything except for the qb file is in my local folder
command = "C:\\TEMPWITHOWNER\\addcustomer\\sdktest.exe \"C:\\Users\\Public\\Documents\\Intuit\\QuickBooks\\Company Files\\Shain Software.qbw\" C:\\TEMPWITHOWNER\\addcustomer\\AddCustomerFROMWEB.xml C:\\TEMPWITHOWNER\\addcustomer\\outputfromsdktestofaddcust.xml";
system(command.c_str());
It sounds like you want to invoke a command-line program from within a PostgreSQL trigger or function.
A usually-better alternative is to have the trigger send a NOTIFY and have a process with a PostgreSQL connection LISTENing for notifications. When a notification comes in, the process can start your program. This is the approach I would recommend; it's a lot cleaner and it means your program doesn't have to run under PostgreSQL's user ID. See NOTIFY and LISTEN.
If you really need to run commands from inside Pg:
You can use PL/Pythonu with os.system or subprocess.check_call; PL/Perlu with system(); etc. All these can run commands from inside Pg if you need to. You can't invoke programs directly from PostgreSQL, you need to use one of the 'untrusted' (meaning fully privileged, not sandboxed) procedural languages to invoke external executables. PL/TCL can probably do it too.
Update:
Your Python code as shown above has several problems:
Using os.system in Python to copy files is just wrong. Use the shutil library: http://docs.python.org/3/library/shutil.html to copy files, and the simple os.mkdir command to create directories.
The double-layered quoting looks wrong; didn't you mean to quote only each argument not the whole command? You should be using subprocess.call instead of os.system anyway.
Your final subprocess.call invocation appears OK, but fails to check the error code so you'll never know if it went wrong; you should use subprocess.check_call instead.
The C++ code also appears to fail to check for errors from the system() invocations so you'll never know if the command it runs fails.
Like the Python code, copying files in C++ by using the copy shell command is generally wrong. Microsoft Windows provides the CopyFile function for this; equivalents or alternatives exist on other platforms and you can use portable-but-less-efficient stream copying too.