Конкатенация путей с использованием удаленного разделителя ОС - PullRequest
0 голосов
/ 12 июня 2019

Я пытаюсь использовать pysftp с внешним сервером Linux, но когда я пытаюсь объединить пути и имена файлов, используя os.path.join() или pathlib.Path(), они по умолчанию по умолчанию используют локальный (Windows) разделитель пути \\,'/'.join() добивается цели, но не похоже на правильный ответ, но может быть лучшим решением.

import os
from pathlib import Path, PosixPath

os.path.join('path', 'to', 'file.txt')
# path\to\file.txt -- Windows

Path('path') / 'to' / 'file.txt'
# path\to\file.txt -- Windows

'/'.join(('path', 'to', 'file.txt'))
# path/to/file.txt -- Posix

Довольно часто я получаю path/to из текущего рабочего каталогаpysftp, так что вместо того, чтобы вручную строить всю строку пути, метод '/'.join() все еще единственный, который работает.

os.path.join('path/to', 'file.txt')
# path/to\file.txt -- Mixed

Path('path/to') / 'file.txt'
# path\to\file.txt -- Windows

'/'.join(('path/to', 'file.txt'))
# path/to/file.txt -- Posix

Есть ли способ заставить os.path.join() или pathlib.Path использовать разделитель Posix при работе в Windows?Я попытался установить атрибут sep для Path, но кажется, что это должно быть сделано для каждого Пути в отдельности, даже если он не поднял AttributeError и, похоже, не хочет, чтобы я создавал экземпляркласс PosixPath напрямую.

p = Path('path/to')
p.sep = '/'
# AttributeError: 'WindowsPath' object has no attribute 'sep'

PosixPath('path') / 'to' / 'file.txt'
# NotImplementedError: cannot instantiate 'PosixPath' on your system

Попытка «обмануть» модуль os с помощью os.name = 'posix' или os.sep = '/' не работает либо

print(os.name)
# nt
print(os.path.join("path", "to", "file.txt"))
# path\to\file.txt -- Windows as expected
os.sep = '/'
print(os.path.join("path", "to", "file.txt"))
# path\to\file.txt -- Windows as expected

os.name = 'posix'
print(os.name)
# posix
print(os.path.join("path", "to", "file.txt"))
# path\to\file.txt -- still Windows.
os.sep = '/'
print(os.path.join("path", "to", "file.txt"))
# path\to\file.txt -- still Windows.

Если это такнезависимо от того, я использую Python 3.7.0

Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)] on win32

1 Ответ

1 голос
/ 12 июня 2019

Похоже, os импортирует либо ntpath, либо posixpath, в зависимости от того, какая операционная система определяется как os.name.К сожалению, мы знаем, что переименование os.name или os.sep не работает без перезагрузки модуля, но вы можете обойтись без прямого импорта двух модулей пути:

>>> import posixpath
>>> import ntpath
>>> ntpath.join('asds','asdf', 'adf.txt')
'asds\\asdf\\adf.txt'
>>> posixpath.join('asdfa','asdf','asdf.txt')
'asdfa/asdf/asdf.txt'

или установки os.path, если хотитеиспользовать os

>>> import os
>>> os.path
<module 'posixpath' from '/home/usr/anaconda3/lib/python3.7/posixpath.py'>
>>> os.path = ntpath
>>> os.path
<module 'ntpath' from '/home/usr/anaconda3/lib/python3.7/ntpath.py'>
>>> os.path.join('asdfa','asd', 'asdf.txt')
'asdfa\\asd\\asdf.txt'
>>> os.path = posixpath
>>> os.path.join('asdfa','asd', 'asdf.txt')
'asdfa/asd/asdf.txt'

Альтернативой использованию os будет использование косой черты / в качестве разделителя пути в вашем коде.Это кроссплатформенный.

'path/to/somefile.txt'

...