Why does Task Manager not run some lines of code in script? - python

Python novice here.
I have a Python script that performs some geodatabase management (reconcile/post versions, compress, etc). I have the following line of code in my script:
createLog = open(str(datetime.date.today()) + ".txt", "w")
along each step of the script I add to the text file with the following statements:
createLog.write("Database connections blocked.\n")
When I run the script in my IDE (PyCharm) I get the desired result: A text file with each step written to the .txt file. When I run it in Task Scheduler no .txt file is created and therefore no log. Everything else runs as far as I can tell. I'm able to track edits made to the data.
I have experienced things like this before with task scheduler but have never been able to resolve the problem in the past.
Any ideas?

I think this is a working directory problem. Python's open function opens a file in the current working directory, NOT in the same folder as the script. This is a common misconception! (Which confused me for ages when learning Python...)
So what is a working directory? Well to quote my good friend Wikipedia:
In computing, the working directory of a process is a directory of a hierarchical file system, if any,[1] dynamically associated with each process. When the process refers to a file using a simple file name or relative path (as opposed to a file designated by a full path from a root directory), the reference is interpreted relative to the current working directory of the process. So for example a process with working directory /rabbit-shoes that asks to create the file foo.txt will end up creating the file /rabbit-shoes/foo.txt.
(Source: https://en.wikipedia.org/wiki/Working_directory)
So how is this working directory selected?
Well it is selected by the parent process of that processes! When you run a program from a shell like bash, the shell (the parent process) helpfully sets the working directory of the program you are running (the child process) to the directory you are currently in. (That is, the directory you cd'd to.)
Since your IDE is smart and helpful, it is starting your Python script process and setting the working directory to the same place the script itself is located. The task scheduler is less helpful... I have absolutely no idea what it is setting the working directory to. However if you search your system, I am sure you will find the log file lying about somewhere!

Related

Xcode - run script only when source file is added or removed

In my project, I have a Python script that scans the source directory and updates a source file with what it finds. I’d like this script to only run when it needs to. At the moment, I have this script in a Run Script build phase with Input Files set to $(PROJECT).xcodeproj/project.pbxproj and Output Files set to the updated source file. This means that the scripts runs when I add new files but it also runs whenever I change project settings. When the script runs unnecessarily, part of the project is recompiled even though none of the source files have changed. This is kind of annoying when all I want to do is tweak some settings.
Is there some way that I can avoid the unnecessary recompilation and just run the script when new source files are added or removed from the project?
I guess I could manually run the script whenever I add or remove a source file.
I think that Xcode is recompiling because the modification date on the file is changed. Python updates the modification date when you flush to a file. So I guess I could just write to the file only when the output is different to the output file. I’m pretty sure reading a file won’t change the modification date. That seems like a lot of fluffing around though. If anyone’s got a better solution, please let me know!

Strange Caching Happening When Running Python Script From Bat

I have a Python script that tags MP3's and renames them. It works when assigning sys args via script parameters in Pycharm.
However, when I call the Python file from a bat, parsing in the same two parameters, I get problems with the file rename.
When printing os.listdir debugging the script, I see a bunch of old test MP3's that are no longer in the dir.
I've checked I'm referencing the correct dir. But it seems like somehow the list of files is cached and being passed over (since I have a validation check - abstracted function in the second part of the if statement blow).
Could it be possible Windows is caching something, or perhaps the .pyc is?
Here is part of the Python in question...
os.chdir(directory)
for files in os.listdir("."):
if files.endswith(".mp3") and not the_file_name_is_valid(files):
log.info("Starting work on: " + files)...
When run from the below bat file, os.listdir(".") produces a list of files that are not current for the working directory. Yet when the script is run from Pycharm it works perfectly.
Here is the bat
echo off
set SET_PREP="set_prep.py"
set DIR=%cd%
set IMAGE="cover_artwork.jpg"
c:\python27\python.exe %SET_PREP% %DIR% %IMAGE%
Pause
Why does running my script with command parameters behave differently to using Script Parameters in Pycharm?

Is it possible to access the launching shortcut directory from a Python executalbe?

I currently have a Python scrip that runs through all Excel files in the current directory and generates a PDF report.
It works fine now but I don't want the users to be anywhere near frozen Python scripts. I created an MSI with cxFreeze which puts the EXE and scripts in the Program Files directory.
What I would like to be able to do is create a shortcut to this executable and pass the directory the shortcut was run from to the Python program so that can be set as the working directory. This would allow the user to move the shortcut to any folder of Excel files and generate a report there.
Does Windows send the location of a opened shortcut to the executable and is there a way to access it from Python?
When you launch a shortcut, Windows changes the working directory to the directory specified in the shortcut, in the Start in field. At this point, Windows has no memory of where the shortcut was stored.
You could change the Start in field to point to the directory that the shortcut is in. But you'd have to do that for every single shortcut, and never make a mistake.
The better approach is to use a script, rather than a shortcut. Place your actual Python script (which we'll call doit.py for sake of example) somewhere in your PYTHONPATH. Then create a single-line Python script that imports it:
import doit
Save it (but don't name it doit.py) and copy it to each directory from which you want to be able to invoke the main script. In doit.py you can use os.getcwd() to find out what directory you're being invoked from.
You could also do it with a batch file. This is a little more flexible in that you can specify the exact name of the script and which Python interpreter should be used, and don't need to store the script in a directory in PYTHONPATH. Also, you don't need to worry about the file's name clashing with the name of a Python module. Simply put this line in a file:
C:\path\to\your\python.exe C:\path\to\your\script.py
Save it as (e.g.) doit.bat and copy it into the directories from which you want to invoke it. As before, your Python script can call os.getcwd() to get the directory. Or you can write it so your Python script accepts it as the first argument, and write your batch file like:
C:\path\to\your\python.exe C:\path\to\your\script.py %cd%
Another thing you can do with the batch file approach is add a pause command to the end so that the user is asked to press a key after the script runs, giving them the opportunity to read any output generated by the script. You could even make this conditional so that it only happens if an error occurs (which requires returning a proper exit code from the script). I'll leave that as an exercise. :-)
Is there a problem with modifying the script to take the directory to process as a command line argument?
You could then configure the different shortcuts to pass in the appropriate directory.
Type the following into a batch file (i.e. script.bat):
python \absolute\path\to\your\script.py %~dp0
pause
Then add these imports at the top of your python file script.py (if not already included):
import os
import sys
And add this to the bottom of the python file (or combine it with a similar statement):
if __name__ == "__main__":
# set current working directory:
if len(sys.argv) > 1:
os.chdir(sys.argv[1])
main()
replace main() with whatever function you want to call or code you want to run.
The following is how I came to my answer:
I tried using kindall's answer and had the following issues:
The first suggestion of storing the script somewhere in PYTHONPATH could not be applied to my situation because my script will be used on a server and needs to be independent of the client computer's python environment (besides having the required pip installations).
I tried calling my python script from a Windows Batch File which could be moved to a different location. Instead of the batch file's location being used as the current working directory, it was C:\Windows.
I tried passing %cd% as an argument to my python script, then setting that to be my CWD. This still resulted in a CWD of C:\Windows.
After reviewing the comments, I tried Eryk Sun's suggestion of instead passing %~dp0 as an argument to the python script. This resulted in the CWD being correctly set to the batch file's location.
I hope this helps others facing similar difficulties.

Sublime/Python: executing a php script via shell in a path that changes

I'm currently using an open-source SCSS compiler, however, every time I make changes to a scss file, I have to run the compiler manually to compile the output. So, to combat this, I edited a Sublime package that allows people to run commands on file saves and it goes like this:
class CommandOnSave(sublime_plugin.EventListener):
def on_post_save(self, view):
settings = view.settings()
current_file = view.file_name()
if current_file.endswith("scss"):
subprocess.call("php path/to/phpscript", shell=True)
Now, the only issue is that one folder in the path changes with every project, and it would be ideal if there was some way to dynamically execute the php script so I don't have to have a settings file with multiple paths in it to accomplish this.
Does anyone know of an easy way to do this without a lot of server overload? The php script always resides four directories down from the scss file. I've tried ../../../.. but that doesn't work (obviously) since the command isn't looking for the file from the current file's path.
Any help is greatly appreciated!

OSX: Creating an automator workflow with Python makes the workflow invalid

I'm making a chat client for OSX, and I wanted it to be able to run as both a .app (for my less technologically inclined users) and as a .py file. I made a workflow app that contained two .py files (an auto-updater and the client itself), run by a python script in the .wflow file. This worked well. However, I couldn't update the updater or workflow script, and the icon was the Python rocket instead of the icon I had chosen. Then, I combined the client .py file with the updater .py file. This still worked, and now I could update the updater. I still couldn't update the python script in the workflow, though, and the icon was still wrong. So, I modified the updater to open the .wflow file, split it into a list (based on python comments in the workflow's python script, such as "#Start") of the stuff before the script, the script's modification time, and the stuff after the script. If the modification time isn't the same as the modification time of the remote file (the one that the updater updates from), then the script downloads the remote .py file, replaces characters (<, >, &) that .wflow files replace ('<' -> "<"), and opens document.wflow with the "w" (write/replace) flag. Then, the stuff that was before the old script, the downloaded script, and the stuff that was after the old script (using file.write(''.join(list))) are all put into document.wflow. This should work, but OSX no longer sees document as an automator file.
As you can see, OSX thinks that the old file is a Workflow, while the new file is a "Microsoft Excel 97-2004 workbook". The IMClient.app (the application that contains document.wflow) gives this message when I try to run it: "The document "IMClient" could not be opened because it is damaged or incomplete." Does anyone know how to fix this?
I'm using python 2.7 and OSX 10.7. The updater is downloading files via FTP.
If clarification is necessary, just ask. I'll post the working and nonworking files if anyone wants them.
EDIT: the file command gives "document.wflow: XML document text" for both the old and new file.

Categories

Resources