How to automatically run python script, when file is added to folder? - python

How can I automatically run a python script, whenever a Word-File is added to a specific folder? This python script would need to work with the Word-File afterwards. My operating system is Windows.
Thanks for your help in advance.

There are several ways to do this and also a special Python package for this
Watchdog Python script for Windows file system
https://pypi.python.org/pypi/watchdog
https://blog.philippklaus.de/2011/08/use-the-python-module-watchdog-to-monitor-directories-for-changes

I have tried all these solutions, but it didnt worked well for me
But!
I have got the solution,
Heres the code:
path_to_watch = "your/path"
print('Your folder path is"',path,'"')
before = dict ([(f, None) for f in os.listdir (path_to_watch)])
while 1:
after = dict ([(f, None) for f in os.listdir (path_to_watch)])
added = [f for f in after if not f in before]
if added:
print("Added: ", ", ".join (added))
break
else:
before = after
I have edited the code, the orginal code is available at http://timgolden.me.uk/python/win32_how_do_i/watch_directory_for_changes.html
The original code was made in python 2x so you need to convert it in python 3.
Note:
Whenever you add any file in path, it prints the text and breaks, and if no files are added then it would continue to run.

How can I automatically run a python script, whenever a Word-File is added to a specific folder?
A solution for this can be found in the following code:
import os
# define path for file
word_file = "path/to/file"
while True:
if os.path.exists(word_file):
# your code here
This code uses the os module to interact with the PC's file system, and starts a while loop that always runs. The conditional statement's condition is the existence of the word_file in the specified location, and you can execute your desired code within the if statement.
I hope this is helpful - let me know if you have any questions!

You may want to look into creating a python service.
How do you run a Python script as a service in Windows?
Like the other answer here, you will create an enduring loop to periodically check the filesystem for your file and then do something if/when it finds it.

you can use watchdog, and create your own eventHandler, like, overwriting original functions inside filesystemeventhandler, by creating a class using filesystemeventhandler(class MyHandler(fileSystemEventHandler):), you can change on_any_event or on_created_ or on_modified.

If you want to run this script infinite you can use this one:
import os
path_to_watch = "C:/Users/someone/"
print('Your folder path is"',path_to_watch,'"')
old = os.listdir(path_to_watch)
print(old)
while True:
new = os.listdir(path_to_watch)
if len(new) > len(old):
newfile = list(set(new) - set(old))
print(newfile[0])
old = new
extension = os.path.splitext(path_to_watch + "/" + newfile[0])[1]
if extension == ".zip":
print("hello")
else:
continue
else:
continue
In this case, I was monitoring for a new .zip file. But when you change it into your wanted extension, it will run something when there's a new word document. When you put the script you want to run when there is a new word document under the "if extension..." it should work.
Code is based on the script from #Faraaz Kurawle.

Related

Python - File Path not found if script run from another directory

I'm trying to run a script that works without issue when I run using in console, but causes issue if I try to run it from another directory (via IPython %run <script.py>)
The issue comes from this line, where it references a folder called "Pickles".
with open('Pickles/'+name+'_'+date.strftime('%y-%b-%d'),'rb') as f:
obj = pickle.load(f)
In Console:
python script.py <---works!
In running IPython (Jupyter) in another folder, it causes a FileNotFound exception.
How can I make any path references within my scripts more robust, without putting the whole extended path?
Thanks in advance!
Since running in the console the way you show works, the Pickles directory must be in the same directory as the script. You can make use of this fact so that you don't have to hard code the location of the Pickles directory, but also don't have to worry about setting the "current working directory" to be the directory containing Pickles, which is what your current code requires you to do.
Here's how to make your code work no matter where you run it from:
with open(os.path.join(os.path.dirname(__file__), 'Pickles', name + '_' + date.strftime('%y-%b-%d')), 'rb') as f:
obj = pickle.load(f)
os.path.dirname(__file__) provides the path to the directory containing the script that is currently running.
Generally speaking, it's a good practice to always fully specify the locations of things you interact with in the filesystem. A common way to do this as shown here.
UPDATE: I updated my answer to be more correct by not assuming a specific path separator character. I had chosen to use '/' only because the original code in the question already did this. It is also the case that the code given in the original question, and the code I gave originally, will work fine on Windows. The open() function will accept either type of path separator and will do the right thing on Windows.
You have to use absolute paths. Also to be cross platform use join:
First get the path of your script using the variable __file__
Get the directory of this file with os.path.dirname(__file__)
Get your relative path with os.path.join(os.path.dirname(__file__), "Pickles", f"{name}_{date.strftime('%y-%b-%d')}")
it gives you:
with open(os.path.join(os.path.dirname(__file__), "Pickles", f"{name}_{date.strftime('%y-%b-%d')}"), 'rb') as f:
obj = pickle.load(f)

While trying to create a txt file with input it doesn't work

I wanted to create a program that saves the user input, im using sublime text 3 and python 3.9, when I run the program the text file with the user input is not appending in the folder that i saved my program
filename = "proba.txt"
name = input("Give me your name. ")
with open(filename, 'a') as f:
f.write(f" {name.title()}\n")
this is the code that i tried to run
sorry for not showing the code here but i ran into problems while trying to rewrite the code here (it was illegible).
The code works fine for me. But sometimes it makes sense to point a destination folder explicitly, just to be sure. I used to do it with pathlib module:
from pathlib import Path
current_folder = Path.cwd() # the folder from which the script was started
filename = current_folder / "proba.txt"
name = input("Give me your name. ")
with open(filename, "a") as f:
f.write(f" {name.title()}\n")
https://docs.python.org/3/library/pathlib.html
Update
As for your case, it looks like you're trying to run the code in VSCode via meny Run code or something like this. Alas, input() doesn't work this way. You need to use Run Python File in Terminal:
Or you can use cmd.exe or powershell or Terminal app and run the python code from there:
python make_file_proba.py
For MacOS it will be likely:
python3 make_file_proba.py

How do I access a similar path to a file that only has a minor difference between computers?

I am trying to access a file from a Box folder as I am working on two different computers. So the file path is pretty much the same except for the username.
I am trying to load a numpy array from a .npy file and I could easily change the path each time, but it would be nice if I could make it universal.
Here is what the line of code looks like on my one computer:
y_pred_walking = np.load('C:/Users/Eric/Box/CMU_MBL/Data/Calgary/4_Best_Results/Walking/Knee/bidir_lstm_50_50/predictions/y_pred_test.npy')
And here is what the line of code looks like on the other computer:
y_pred_walking = 'C:/Users/erapp/Box/CMU_MBL/Data/Calgary/4_Best_Results/Walking/Knee/bidir_lstm_50_50/predictions/y_pred_test.npy'
The only difference is that the username on one computer is Eric and the other is erapp, but is there a way where I can make the line universal to all computers where all computers will have the Box folder?
You could either save the file to a path that doesn't depend on the user: e.g. 'C:/Box/CMU_MBL/Data/Calgary/4_Best_Results/Walking/Knee/bidir_lstm_50_50/predictions/y_pred_test.npy'
Or you could do some string formatting. One way would be with an environment or configuration variable that indicates which is the relevant user, and then for your load statement:
import os
current_user = os.environ.get("USERNAME") # assuming you're running on the Windows box as the relevant user
# Now load the formatted string. f-strings are better, but this is more obvious since f-strings are still very new to Python
y_pred_walking = 'C:/Users/{user}/Box/CMU_MBL/Data/Calgary/4_Best_Results/Walking/Knee/bidir_lstm_50_50/predictions/y_pred_test.npy'.format(user=current_user)
Yes, there is a way, at least for the problem as it is right now solution is pretty simple: to use f-strings
user='Eric'
y_pred_walking =np.load(f'C:/Users/{user}/Box/CMU_MBL/Data/Calgary/4_Best_Results/Walking/Knee/bidir_lstm_50_50/predictions/y_pred_test.npy')
or more general
def pred_walking(user):
return np.load(f'C:/Users/{user}/Box/CMU_MBL/Data/Calgary/4_Best_Results/Walking/Knee/bidir_lstm_50_50/predictions/y_pred_test.npy')
so on any machine you just do
y_pred_walking=pred_walking(user)
with defined user before, to receive the result
Simply search the folders recursivly for your file:
filename = 'y_pred_test.npy'
import os
import random
# creates 1000 directories with a 1% chance of having the file as well
for k in range(20):
for i in range(10):
for j in range(5):
os.makedirs(f"./{k}/{i}/{j}")
if random.randint(1,100) == 2:
with open(f"./{k}/{i}/{j}/{filename}","w") as f:
f.write(" ")
# search the directories for your file
found_in = []
# this starts searching in your current folder - you can give it your c:\Users\ instead
for root,dirs,files in os.walk("./"):
if filename in files:
found_in.append(os.path.join(root,filename))
print(*found_in,sep = "\n")
File found in:
./17/3/1/y_pred_test.npy
./3/8/1/y_pred_test.npy
./16/3/4/y_pred_test.npy
./16/5/3/y_pred_test.npy
./14/2/3/y_pred_test.npy
./0/5/4/y_pred_test.npy
./11/9/0/y_pred_test.npy
./9/8/1/y_pred_test.npy
If you get read errors because of missing file/directory permissions you can start directly in the users folder:
# Source: https://stackoverflow.com/a/4028943/7505395
from pathlib import Path
home = str(Path.home())
found_in = []
for root,dirs,files in os.walk(home):
if filename in files:
found_in.append(os.path.join(root,filename))
# use found_in[0] or break as soon as you find first file
You can use the expanduser function in the os.path module to modify a path to start from the home directory of a user
https://docs.python.org/3/library/os.path.html#os.path.expanduser

Python creates locked files on Ubuntu

I just ran into a problem, which is probably easy to fix - well, for you guys.
I try to create a directory, change to it, create a file in that directory and appened to that file. Everything works fine - except it marks the directory/file as locked and that isn't very convenient for me.
I am running my script as root, because I need to. When I run it normally that problem doesn't occur. I am on Ubuntu and down below is some example code plus a picture of the permissions of the given file, thanks!
import os
os.makedirs("foo", exist_ok = True)
os.chdir("foo")
with open("oof", "a") as f:
f.write("something" + "\n")
As you said you run the script as root so other users can not access this file.
You can change directory permissions:
from subprocess import call
call(['chmod', 'mode', 'path'])

Running python script with new directories

I have recently begun working on a new computer. All my python files and my data are in the dropbox folder, so having access to the data is not a problem. However, the "user" name on the file has changed. Thus, none of my os.chdir() operations work. Obviously, I can modify all of my scripts using a find and replace, but that won't help if I try using my old computer.
Currently, all the directories called look something like this:
"C:\Users\Old_Username\Dropbox\Path"
and the files I want to access on the new computer look like:
"C:\Users\New_Username\Dropbox\Path"
Is there some sort of try/except I can build into my script so it goes through the various path-name options if the first attempt doesn't work?
Thanks!
Any solution will involve editing your code; so if you are going to edit it anyway - its best to make it generic enough so it works on all platforms.
In the answer to How can I get the Dropbox folder location programmatically in Python? there is a code snippet that you can use if this problem is limited to dropbox.
For a more generic solution, you can use environment variables to figure out the home directory of a user.
On Windows the home directory is location is stored in %UserProfile%, on Linux and OSX it is in $HOME. Luckily Python will take care of all this for you with os.path.expanduser:
import os
home_dir = os.path.expanduser('~')
Using home_dir will ensure that the same path is resolved on all systems.
Thought the file sq.py with these codes(your olds):
C:/Users/Old_Username/Dropbox/Path
for x in range:
#something
def Something():
#something...
C:/Users/Old_Username/Dropbox/Path
Then a new .py file run these codes:
with open("sq.py","r") as f:
for x in f.readlines():
y=x
if re.findall("C:/Users/Old_Username/Dropbox/Path",x) == ['C:/Users/Old_Username/Dropbox/Path']:
x="C:/Users/New_Username/Dropbox/Path"
y=y.replace(y,x)
print (y)
Output is:
C:/Users/New_Username/Dropbox/Path
for x in range:
#something
def Something():
#something...
C:/Users/New_Username/Dropbox/Path
Hope its your solution at least can give you some idea dealing with your problem.
Knowing that eventually I will move or rename my projects or scripts, I always use this code right at the beginning:
import os, inspect
this_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
this_script = inspect.stack()[0][1]
this_script_name = this_script.split('/')[-1]
If you call your script not with the full but a relative path, then this_script will also not contain a full path. this_dir however will always be the full path to the directory.

Categories