Как создать пустые файлы и использовать os-модуль в Python 3? [Дубликат]

Возможно, потому, что в std :: map нет оператора const []. оператор [] добавит элемент, который вы ищете, если он его не найдет. Поэтому используйте метод find (), если вы хотите искать без возможности добавления.

231
задан 7 revs, 2 users 87% 1 July 2012 в 06:52
поделиться

9 ответов

Это пытается быть немного более свободным от гонки, чем другие решения. (Ключевое слово with является новым в Python 2.5.)

import os
def touch(fname, times=None):
    with open(fname, 'a'):
        os.utime(fname, times)

Грубо эквивалентно этому.

import os
def touch(fname, times=None):
    fhandle = open(fname, 'a')
    try:
        os.utime(fname, times)
    finally:
        fhandle.close()

Теперь, чтобы действительно сделать его без гонок, вам нужно использовать futimes и изменить временную метку открытого дескриптора файла вместо того, чтобы открывать файл, а затем изменять временную метку на имени файла (которое могло быть переименовано). К сожалению, Python, похоже, не предоставляет способ вызова futimes без прохождения ctypes или подобного ...


EDIT

Как отмечено Nate Parsons , Python 3.3 добавит , указав дескриптор файла (когда os.supports_fd ) к функциям, таким как os.utime , который будет использовать syscall futimes вместо utimes syscall под капотом. Другими словами:

import os
def touch(fname, mode=0o666, dir_fd=None, **kwargs):
    flags = os.O_CREAT | os.O_APPEND
    with os.fdopen(os.open(fname, flags=flags, mode=mode, dir_fd=dir_fd)) as f:
        os.utime(f.fileno() if os.utime in os.supports_fd else fname,
            dir_fd=None if os.supports_fd else dir_fd, **kwargs)
216
ответ дан 6 revs, 2 users 96% 16 August 2018 в 00:58
поделиться
  • 1
    Это реальное решение - и это то, как touch (1) в coreutils делает это, если futimes () недоступен. futimes не является переносной функцией и даже не существует на старых ядрах Linux 2.6, поэтому вам нужно иметь дело с ENOSYS и вернуться к утилите, даже если вы ее используете. – Glenn Maynard 21 July 2009 в 19:45
  • 2
    (Ошибка Корректировки выше: «Это» = открыть («a») + futimes.) К счастью, трудно подумать о случае, когда на самом деле имеет место условие гонки, не использующее futimes. "Неправильный" в результате вы можете переименовать файл open () и utime (), и в этом случае вы не создадите новый файл и не коснетесь старого. Это может иметь значение, но в большинстве случаев это не так. – Glenn Maynard 21 July 2009 в 19:52
  • 3
    cygwin touch может делать свою магию только для чтения, но этот код не может. Однако, похоже, это работает, если я окружаю его с помощью try: & lt; code & gt; кроме IOError как e: (проверить e.errno) os.utime (имя файла, время) – dash-tom-bang 20 May 2011 в 03:09
  • 4
    FYI, кажется, что futimes был добавлен в 3.3 – Nate Parsons 23 August 2012 в 17:36
  • 5
    Примечание: встроенная функция file была удалена из Python 3, и вместо этого нужно использовать open. Я полностью пропустил это, потому что подсветка синтаксиса редактора, который я использую (gedit), по-прежнему нацелена на Python 2. – Bart 24 January 2014 в 10:53

Сложность (возможно, ошибка):

def utime(fname, atime=None, mtime=None)
    if type(atime) is tuple:
        atime, mtime = atime

    if atime is None or mtime is None:
        statinfo = os.stat(fname)
        if atime is None:
            atime = statinfo.st_atime
        if mtime is None:
            mtime = statinfo.st_mtime

    os.utime(fname, (atime, mtime))


def touch(fname, atime=None, mtime=None):
    if type(atime) is tuple:
        atime, mtime = atime

    open(fname, 'a').close()
    utime(fname, atime, mtime)

Это также позволяет установить время доступа или модификации, например, GNU touch.

3
ответ дан 2 revs 16 August 2018 в 00:58
поделиться
  • 1
    Fail : with open(fn,'a'): pass или альтернатива open(fn, 'a').close() не изменяют время изменения, используя Python 2.7.5 в Red Hat 7 (файловая система - XFS). На моей платформе эти решения просто создают пустой файл, если он не существует. : - / – olibre 6 June 2017 в 13:58

Почему бы не попробовать это?:

import os

def touch(fname):
    try:
        os.utime(fname, None)
    except OSError:
        open(fname, 'a').close()

Я считаю, что это устраняет любое состояние гонки, которое имеет значение. Если файл не существует, будет выбрано исключение.

Единственное возможное условие гонки здесь - если файл создается до вызова функции open (), но после os.utime (). Но это не имеет значения, потому что в этом случае время модификации будет таким, как ожидалось, поскольку оно должно было произойти во время вызова touch ().

25
ответ дан 2 revs, 2 users 89% 16 August 2018 в 00:58
поделиться

Похоже, что это новое, как у Python 3.4 - pathlib .

from pathlib import Path

Path('path/to/file.txt').touch()

Это создаст file.txt на пути.

-

Path.touch (mode = 0o777, exist_ok = True)

Создайте файл по данному пути. Если задан режим, он сочетается с значением «umask» процесса, чтобы определить режим файла и флаги доступа. Если файл уже существует, функция будет успешной, если exist_ok истинно (и время его модификации обновляется до текущего времени), в противном случае FileExistsError будет поднят.

116
ответ дан 2 revs, 2 users 97% 16 August 2018 в 00:58
поделиться
  • 1
    На Python2.7: pip install pathlib – Andre Miras 24 October 2017 в 17:54
  • 2
    note to self: используйте Path('/some/path').mkdir(), если каталог, содержащий файл touch() ed, еще не существует. – JacobIRR 7 July 2018 в 05:04
def touch(fname):
    if os.path.exists(fname):
        os.utime(fname, None)
    else:
        open(fname, 'a').close()
34
ответ дан 3 revs, 2 users 93% 16 August 2018 в 00:58
поделиться
  • 1
    В этом решении есть потенциальное состояние гонки: если файл не существует и создается другим процессом до того, как эта функция дойдет до вызова open(), содержимое файла будет усечено. Вместо этого предложите использовать режим 'a'. – Greg Hewgill 21 July 2009 в 10:25
  • 2
    Согласовано. Правильное решение: def touch (fname): open (fname, 'wa'). Close () – stepancheg 21 July 2009 в 11:25
  • 3
    @Greg, в то время как он решает проблему потенциального гоночного состояния, open(fname, 'a').close() не изменится. – SilentGhost 21 July 2009 в 11:40
  • 4
    @SilentGhost: Это правда, но все в порядке, потому что, если файл существует, он был создан только just . Конечно, вы оставите звонок на os.utime() там для ранее существовавших файлов. – Greg Hewgill 21 July 2009 в 11:43
  • 5
    Почему бы не просто открыть, чтобы убедиться, что он существует, а затем вызвать utime? – itsadok 21 July 2009 в 11:52

Может показаться логичным создать строку с требуемыми переменными и передать ее в os.system:

touch = 'touch ' + dir + '/' + fileName
os.system(touch)

Это неадекватно несколькими способами (например, он не обрабатывает пробелы), так что не делайте этого.

Более надежным методом является использование подпроцесса:

subprocess.call(['touch', os.path.join(dirname, fileName)])

Хотя это намного лучше, чем использование подоболочки (с os.system), это по-прежнему подходит только для быстрого и грязного сценариев; используйте принятый ответ для кросс-платформенных программ.

1
ответ дан 3 revs, 3 users 43% 16 August 2018 в 00:58
поделиться
  • 1
    Это не очень безопасно: что происходит, когда в имени файла есть пробел? – ayke 8 July 2012 в 11:54
  • 2
    subprocess.call(['touch', os.path.join(dirname, fileName)]) намного лучше, чем использование подоболочки (с os.system). Но все же, используйте это только для быстрых и грязных сценариев, используйте принятый ответ для кросс-платформенных программ. – ayke 8 July 2012 в 11:58
  • 3
    touch не является кросс-платформенной доступной командой (например, Windows) – Mike T 21 May 2018 в 06:23

Упрощенный:

def touch(fname):
    open(fname, 'a').close()
    os.utime(fname, None)
  • open гарантирует, что там есть файл
  • , utime гарантирует обновление временных меток

Теоретически, возможно, кто-то удалит файл после open, вызывая утилизацию для возникновения исключения. Но, возможно, все в порядке, так как случилось что-то плохое.

3
ответ дан 4 revs 16 August 2018 в 00:58
поделиться

"open (имя_файла, 'a'). close ()" не работает для меня в Python 2.7 на Windows. «os.utime (имя_файла, нет)» отлично работало.

Кроме того, мне пришлось рекурсивно обращаться ко всем файлам в каталоге с датой, более старой, чем какая-либо дата. Я создал hte follow, основанный на очень полезном ответе ephemient.

def touch(file_name):
    # Update the modified timestamp of a file to now.
    if not os.path.exists(file_name):
        return
    try:
        os.utime(file_name, None)
    except Exception:
        open(file_name, 'a').close()

def midas_touch(root_path, older_than=dt.now(), pattern='**', recursive=False):
    '''
    midas_touch updates the modified timestamp of a file or files in a 
                directory (folder)

    Arguements:
        root_path (str): file name or folder name of file-like object to touch
        older_than (datetime): only touch files with datetime older than this 
                   datetime
        pattern (str): filter files with this pattern (ignored if root_path is
                a single file)
        recursive (boolean): search sub-diretories (ignored if root_path is a 
                  single file)
    '''
    # if root_path NOT exist, exit
    if not os.path.exists(root_path):
        return
    # if root_path DOES exist, continue.
    else:
        # if root_path is a directory, touch all files in root_path
        if os.path.isdir(root_path):
            # get a directory list (list of files in directory)
            dir_list=find_files(root_path, pattern='**', recursive=False)
            # loop through list of files
            for f in dir_list:
                # if the file modified date is older thatn older_than, touch the file
                if dt.fromtimestamp(os.path.getmtime(f)) < older_than:
                    touch(f)
                    print "Touched ", f
        # if root_path is a file, touch the file
        else:
            # if the file modified date is older thatn older_than, touch the file
            if dt.fromtimestamp(os.path.getmtime(f)) < older_than:
                touch(root_path)
1
ответ дан cadvena 16 August 2018 в 00:58
поделиться

Вот код, который использует ctypes (тестируется только в Linux):

from ctypes import *
libc = CDLL("libc.so.6")

#  struct timespec {
#             time_t tv_sec;        /* seconds */
#             long   tv_nsec;       /* nanoseconds */
#         };
# int futimens(int fd, const struct timespec times[2]);

class c_timespec(Structure):
    _fields_ = [('tv_sec', c_long), ('tv_nsec', c_long)]

class c_utimbuf(Structure):
    _fields_ = [('atime', c_timespec), ('mtime', c_timespec)]

utimens = CFUNCTYPE(c_int, c_char_p, POINTER(c_utimbuf))
futimens = CFUNCTYPE(c_int, c_char_p, POINTER(c_utimbuf)) 

# from /usr/include/i386-linux-gnu/bits/stat.h
UTIME_NOW  = ((1l << 30) - 1l)
UTIME_OMIT = ((1l << 30) - 2l)
now  = c_timespec(0,UTIME_NOW)
omit = c_timespec(0,UTIME_OMIT)

# wrappers
def update_atime(fileno):
        assert(isinstance(fileno, int))
        libc.futimens(fileno, byref(c_utimbuf(now, omit)))
def update_mtime(fileno):
        assert(isinstance(fileno, int))
        libc.futimens(fileno, byref(c_utimbuf(omit, now)))

# usage example:
#
# f = open("/tmp/test")
# update_mtime(f.fileno())
7
ответ дан eug 16 August 2018 в 00:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: