HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Torrent File Remover

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
filetorrentremover

Problem

This script to locate torrent files in a given directory, and if they have been seeding for 2 weeks, delete the files.

I realize the comments are overboard. The reason for that is it's being shared with people who don't program.

What should I have done differently?

```
import os # for listdir(), path(), remove(), and getctime()
from time import time, ctime, sleep
import datetime as dt # datetime to compare dates

# Path to torrents
torrents_folder = r'C:\users\user\torrents\folder'
# Torrent files as a list
torrents = os.listdir(torrents_folder)
# Months will be used to swap month prefix and corresponding month number
months = {"Jan": "01", "Feb": "02", "Mar": "03", "Apr": "04", "May": "05", "Jun": "06", "Jul": "07", "Aug": "08",
"Sep": "09", "October": "10", "Nov": "11", "Dec": "12", }
# Set the number of days to elapse from creation date before file is deleted
days_to_wait = dt.timedelta(days=14)

# function to remove torrent
def torrent_remover(month):
# Format the date, casting month to string
start_date = dt.datetime.strptime(str(month), "%m %d %Y")
# Elapsed Time. See line 12
end_date = start_date + days_to_wait
# Today's date for comparison
today = dt.datetime.today()

if end_date <= today:
print("Removing: ", torrent, "\tTorrent expired on", end_date)
# Create full path from the torrent folder and torrent file
torrent_files = os.path.join(torrents_folder, torrent)
# Delete the torrents
os.remove(torrent_files)
else:
print("Nothing to remove")
exit()

# Start the loop
for torrent in torrents:
if torrent.endswith(".torrent"):
# Get date time from each file then join file and folder to create full path
date = ctime(os.path.getctime(os.path.join(torrents_folder, torrent)))
# Remove the timestamp
remove_timestamp = date.replace(date[11:19], "")
# Remove

Solution

You could do with learning some of the more powerful tools in Python, such as pathlib.

Tracing control flow, instead of

torrents_folder = r'C:\users\user\torrents\folder'
torrents = os.listdir(torrents_folder)

for torrent in torrents:
    if torrent.endswith(".torrent"):
        ...


you can do

torrents_folder = Path(r'C:\users\user\torrents\folder')
for torrent_path in torrents_folder.glob("*.torrent"):
    ...


Then to get the date you can do just

datetime.date.fromtimestamp(torrent_path.stat().st_ctime)


Before I leave this, though, I should warn that your

text.replace(text[a:b], "")


to remove a slice is error-prone if that slice ever appears elsewhere. Instead try something like

text = text[:a] + text[b:]


Your if after

month = [month for month in months if month in new_date][0]
if month in new_date:


looks strange - of course it will be True since you've just checked for it.

Anyway, this can now be avoided entirely since we have a date object.

You run torrent_remover(date) (although you call it month in the call signature!), but you also need the torrent_path. It turns out you're passing this as a global! That's bad!

Instead, add another parameter so you have

def torrent_remover(path, date):


Your checks can then just be

end_date = date + days_to_wait
today = dt.datetime.today()

if end_date <= today:
    ...
else:
    ...


Your

print("Removing: ", torrent, "\tTorrent expired on", end_date)
torrent_files = os.path.join(torrents_folder, torrent)
os.remove(torrent_files)


Is misnamed (you only remove one file), but now can be just

print("Removing: ", torrent_path, "\tTorrent expired on", end_date)
torrent_path.unlink()


and your other path looks wrong:

print("Nothing to remove")
exit()


since exit quits the process entirely.

days_to_wait is a global constant, so should be uppercase. However, I would put the code in a main function and just pass it to the remover.

I would let torrent_remover get the date itself, simplifying the main loop.

Finally, your printing adds spaces between every part. One way to fix that is

print(a, b, c, sep="")


but it seems better to use formatting here:

print("{}{}{}".format(a, b, c))


This all gives

from datetime import date, timedelta
from pathlib import Path

def torrent_remover(path, shelf_life):
    created_on = date.fromtimestamp(torrent_path.stat().st_ctime)
    expired_on = created_on + shelf_life

    if expired_on <= date.today():
        print("Removing: {}\tTorrent expired on {}".format(torrent_path, expired_on))
        torrent_path.unlink()

def main():
    shelf_life = timedelta(days=14)
    torrents_folder = Path(r"C:\users\user\torrents\folder")

    for torrent_path in torrents_folder.glob("*.torrent"):
        torrent_remover(torrent_path, shelf_life)

if __name__ == '__main__':
    main()


which I hope you'll agree is simpler. To add a check for if any file has been removed, try something like

from datetime import date, timedelta
from pathlib import Path

def torrent_remover(path, shelf_life):
    created_on = date.fromtimestamp(torrent_path.stat().st_ctime)
    expired_on = created_on + shelf_life

    if expired_on <= date.today():
        print("Removing: {}\tTorrent expired on {}".format(torrent_path, expired_on))
        torrent_path.unlink()
        return True

    return False

def main():
    shelf_life = timedelta(days=14)
    torrent_paths = Path(r"C:\users\user\torrents\folder").glob("*.torrent")
    removed = sum(torrent_remover(path, shelf_life) for path in torrent_paths)

    if not removed:
        print("Nothing to remove")

if __name__ == '__main__':
    main()


This is untested.

Code Snippets

torrents_folder = r'C:\users\user\torrents\folder'
torrents = os.listdir(torrents_folder)

for torrent in torrents:
    if torrent.endswith(".torrent"):
        ...
torrents_folder = Path(r'C:\users\user\torrents\folder')
for torrent_path in torrents_folder.glob("*.torrent"):
    ...
datetime.date.fromtimestamp(torrent_path.stat().st_ctime)
text.replace(text[a:b], "")
text = text[:a] + text[b:]

Context

StackExchange Code Review Q#84917, answer score: 4

Revisions (0)

No revisions yet.