Czy python ma wbudowaną funkcjonalność? Moim pomysłem jest, że działa on w taki sam sposób, jak system operacyjny działa, jeśli plik jest wyprowadzany do katalogu, w którym plik o tej nazwie już istnieje. Np. Jeśli istnieje plik "plik.pdf", utworzy "plik2.pdf", a następnym razem "plik3.pdf".python: Utwórz plik, ale jeśli istnieje, dodaj numer
Odpowiedz
W pewnym sensie Python ma tę funkcję wbudowaną w moduł tempfile
. Niestety, musisz wejść do prywatnej zmiennej globalnej, tempfile._name_sequence
. Oznacza to, że oficjalnie, tempfile
nie daje gwarancji, że w przyszłych wersjach _name_sequence
nawet istnieje - jest to szczegół implementacji. Ale jeśli jesteś w porządku z użyciem tak, to pokazuje, w jaki sposób można tworzyć unikatowe nazwy plików formie file#.pdf
w określonym katalogu, takich jak /tmp
:
import tempfile
import itertools as IT
import os
def uniquify(path, sep = ''):
def name_sequence():
count = IT.count()
yield ''
while True:
yield '{s}{n:d}'.format(s = sep, n = next(count))
orig = tempfile._name_sequence
with tempfile._once_lock:
tempfile._name_sequence = name_sequence()
path = os.path.normpath(path)
dirname, basename = os.path.split(path)
filename, ext = os.path.splitext(basename)
fd, filename = tempfile.mkstemp(dir = dirname, prefix = filename, suffix = ext)
tempfile._name_sequence = orig
return filename
print(uniquify('/tmp/file.pdf'))
Dziękuję za odpowiedź! Tricky rzeczy, aby dowiedzieć się z dokumentów;) Ja wybieram własne, prostsze podejście, ale ta odpowiedź wyraźnie odpowiada na to, co zastanawiałem – Parham
Tak, to jest prawdopodobnie mądry wybór, jeśli nie potrzebujesz specjalnych możliwości 'tempfile '. Moduł 'tempfile' stara się unikać określonych warunków wyścigu, bezpieczeństwa i ataków typu" odmowa usługi ". Korzystanie z numeracji sekwencyjnej powoduje, że powyższy kod jest podatny na atak typu "odmowa usługi".I nie jestem do końca pewien, czy powyższe jest bezpieczne także przed warunkami wyścigowymi lub innymi zagrożeniami bezpieczeństwa. – unutbu
starałem się wdrożyć to samo w moim projekcie ale odpowiedź @ unutbu wydawała zbyt „ciężki” dla moich potrzeb więc wymyśliłem następujący kod wreszcie:
import os
index = ''
while True:
try:
os.makedirs('../hi'+index)
break
except WindowsError:
if index:
index = '('+str(int(index[1:-1])+1)+')' # Append 1 to number in brackets
else:
index = '(1)'
pass # Go and try create file again
wszelki wypadek ktoś natknął się na to i wymaga czegoś prostszego.
Ponieważ hackowanie plików tymczasowych A) jest hackerem i B) nadal wymaga przyzwoitej ilości kodu, poszedłem z ręczną implementacją. Zasadniczo trzeba:
- Sposobem Safely create a file if and only if it does not exist (to jest to, co daje nam Hack tempfile).
- Generator nazw plików.
- Funkcja owijania w celu ukrycia bałaganu.
ja zdefiniował safe_open które mogą być używane tak jak otwarte:
def iter_incrementing_file_names(path):
"""
Iterate incrementing file names. Start with path and add " (n)" before the
extension, where n starts at 1 and increases.
:param path: Some path
:return: An iterator.
"""
yield path
prefix, ext = os.path.splitext(path)
for i in itertools.count(start=1, step=1):
yield prefix + ' ({0})'.format(i) + ext
def safe_open(path, mode):
"""
Open path, but if it already exists, add " (n)" before the extension,
where n is the first number found such that the file does not already
exist.
Returns an open file handle. Make sure to close!
:param path: Some file name.
:return: Open file handle... be sure to close!
"""
flags = os.O_CREAT | os.O_EXCL | os.O_WRONLY
if 'b' in mode and platform.system() == 'Windows':
flags |= os.O_BINARY
for filename in iter_incrementing_file_names(path):
try:
file_handle = os.open(filename, flags)
except OSError as e:
if e.errno == errno.EEXIST:
pass
else:
raise
else:
return os.fdopen(file_handle, mode)
# Example
with safe_open("some_file.txt", "w") as fh:
print("Hello", file=fh)
Nie testowałem tego jeszcze, ale to powinno działać, iteracji nad możliwych nazw plików do pliku w pytaniu nie istnieje w które wskazują, że się łamie.
def increment_filename(fn):
fn, extension = os.path.splitext(path)
n = 1
yield fn + extension
for n in itertools.count(start=1, step=1)
yield '%s%d.%s' % (fn, n, extension)
for filename in increment_filename(original_filename):
if not os.isfile(filename):
break
niedawno natknąłem samo i tutaj jest moje podejście:
import os
file_name = "file_name.txt"
if os.path.isfile(file_name):
expand = 1
while True:
expand += 1
new_file_name = file_name.split(".txt")[0] + str(expand) + ".txt"
if os.path.isfile(new_file_name):
continue
else:
file_name = new_file_name
break
Działa to dla mnie. Początkowa nazwa pliku jest 0.yml
, jeśli istnieje, to doda jeden aż spełnienia wymogu
import os
import itertools
def increment_filename(file_name):
fid, extension = os.path.splitext(file_name)
yield fid + extension
for n in itertools.count(start=1, step=1):
new_id = int(fid) + n
yield "%s%s" % (new_id, extension)
def get_file_path():
target_file_path = None
for file_name in increment_filename("0.yml"):
file_path = os.path.join('/tmp', file_name)
if not os.path.isfile(file_path):
target_file_path = file_path
break
return target_file_path
To będzie na ogół funkcją aplikacji lub programu tworzenia plików więc nie ma, nie ma natywnej funkcjonalności tak . Biorąc pod uwagę katalog i nazwę pliku, możesz sam coś stworzyć. – timc
sprawdź to http://code.activestate.com/recipes/578116-move-files-with-rename-if-required/ – avasal
sprawdź ['filename_fix_existing (nazwa pliku)'] (https://github.com/steveeJ /python-wget/blob/master/wget.py#L72) –