Как использовать относительный импорт? [Дубликат]

Я работал над одной и той же проблемой в течение полудня и, наконец, понял это.

Для неявного FTP TLS / SSL (defualt port 990) наша клиентская программа должна создать TLS / SSL соединение сразу после создания сокета. Но класс python FTP_TLS не перезагружает функцию подключения из класса FTP. Мы должны исправить это:

class tyFTP(ftplib.FTP_TLS):
  def __init__(self,
               host='',
               user='',
               passwd='',
               acct='',
               keyfile=None,
               certfile=None,
               timeout=60):

    ftplib.FTP_TLS.__init__(self,
                            host=host,
                            user=user,
                            passwd=passwd,
                            acct=acct,
                            keyfile=keyfile,
                            certfile=certfile,
                            timeout=timeout)

  def connect(self, host='', port=0, timeout=-999):
    """Connect to host.  Arguments are:
    - host: hostname to connect to (string, default previous host)
    - port: port to connect to (integer, default previous port)
    """
    if host != '':
        self.host = host
    if port > 0:
        self.port = port
    if timeout != -999:
        self.timeout = timeout
    try:
        self.sock = socket.create_connection((self.host, self.port), self.timeout)
        self.af = self.sock.family
        # add this line!!!
        self.sock = ssl.wrap_socket(self.sock,
                                    self.keyfile,
                                    self.certfile,
                                    ssl_version=ssl.PROTOCOL_TLSv1)
        # add end
        self.file = self.sock.makefile('rb')
        self.welcome = self.getresp()
    except Exception as e:
        print(e)
    return self.welcome

Этот производный класс перезагружает функцию подключения и создает оболочку вокруг сокета для TLS. После успешного подключения и входа на FTP-сервер вам необходимо вызвать: FTP_TLS.prot_p() перед выполнением любой команды FTP!

Надеюсь, это поможет ^ _ ^

163
задан baudtack 27 May 2009 в 22:43
поделиться

12 ответов

Вместо использования

import os
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'relative/path/to/file/you/want')

, как в принятом ответе, было бы более надежно использовать:

import inspect
import os
dirname = os.path.dirname(os.path.abspath(inspect.stack()[0][1]))
filename = os.path.join(dirname, 'relative/path/to/file/you/want')

, поскольку использование __file__ вернет файл, из которого модуль был загружен, если он был загружен из файла, поэтому, если файл со сценарием вызывается из другого места, возвращаемый каталог будет неправильным.

Эти ответы дают более подробную информацию: https://stackoverflow.com/a/31867043/5542253 и https://stackoverflow.com/a/50502/5542253

197
ответ дан Martijn Pieters 19 August 2018 в 17:31
поделиться
  • 1
    Правильно ли я считаю, что файл не всегда доступен (например, когда вы запускаете файл напрямую, а не импортируете его)? – Stephen Edmonds 28 May 2009 в 13:43
  • 2
    @Stephen Edmonds Я использую для него файл, который я запускаю, а не импорт, и он отлично работает. – baudtack 4 June 2009 в 04:37
  • 3
    Обратите внимание, что вы должны использовать os.path.join всюду для переносимости: filename = os.path.join(dir, 'relative', 'path', 'to', 'file', 'you' , 'want') – ford 6 February 2014 в 19:51
  • 4
    os.path.dirname(__file__) может дать пустую строку, вместо этого используйте os.path.dirname(os.path.abspath(__file__)) – Dmitry Trofimov 10 March 2015 в 23:03
  • 5
    Это незначительная вещь, но ПОЖАЛУЙСТА не используйте dir как имя переменной, так как она встроена. – David 14 July 2015 в 19:18
  • 6
    inspect.stack() - это дорогая функция для вызова. Он извлекает информацию для всех кадров стека, которые вы затем отбрасываете и получаете только верхнюю. Он в основном называет inspect.getfile() объектом модуля, который просто возвращает module.__file__. Вы гораздо лучше используете __file__. – Martijn Pieters♦ 12 May 2018 в 19:05
207
ответ дан Martijn Pieters 31 October 2018 в 04:07
поделиться

Этот код вернет абсолютный путь к основному скрипту.

import os
def whereAmI():
    return os.path.dirname(os.path.realpath(__import__("__main__").__file__))

Это будет работать даже в модуле.

4
ответ дан BookOwl 19 August 2018 в 17:31
поделиться
  • 1
    Вместо повторного импорта вы будете использовать sys.modules['__main__'].__file__. – Martijn Pieters♦ 12 May 2018 в 19:05

Привет, прежде всего, вы должны понимать функции os.path.abspath (path) и os.path.relpath (path)

Короче os.path.abspath (path) делает относительный путь к абсолютный путь. И если предоставленный путь сам по себе является абсолютным путем, то функция возвращает тот же путь.

аналогично os.path.relpath (path) делает абсолютный путь к относительному пути. И если предоставленный путь сам по себе является относительным путем, функция возвращает один и тот же путь.

Ниже приведен пример, который вы можете правильно понимать в приведенной выше концепции :

предположим, что у меня есть файл input_file_list.txt, который содержит список входных файлов, которые будут обрабатываться моим скриптом python.

D: \ conc \ input1.dic

D: \ conc \ input2 .dic

D: \ Copyioconc \ input_file_list.txt

Если вы видите выше структуру папок, input_file_list.txt присутствует в папке Copyofconc, а файлы, которые должны обрабатываться скриптом python, присутствует в папке conc

Но содержимое файла input_file_list.txt выглядит так:

.. \ conc \ input1.dic

.. \ conc \ input2.dic

И мой скрипт python присутствует в D: диске.

И относительный путь, указанный в файле input_file_list.txt, относится к пути input_file_list.txt file.

Итак, когда скрипт python должен выполнить текущий рабочий каталог (используйте os.getcwd (), чтобы получить pa th)

Поскольку мой относительный путь относится к input_file_list.txt, то есть «D: \ Copyofconc», мне нужно изменить текущий рабочий каталог на «D: \ Copyofconc».

Поэтому мне нужно использовать os.chdir ('D: \ Copyofconc'), поэтому текущий рабочий каталог должен быть «D: \ Copyofconc».

Теперь, чтобы получить файлы input1.dic и input2 .dic, я прочитаю строки «.. \ conc \ input1.dic», затем будет использовать команду

input1_path = os.path.abspath ('.. \ conc \ input1.dic') ( для изменения относительного пути к абсолютному пути. Здесь в качестве текущего рабочего каталога находится «D: \ Copyofconc», к файлу «. \ Conc \ input1.dic» следует обращаться относительно «D: \ Copyofconc»)

, поэтому input1_path должен быть «D: \ конц \ input1.dic "

3
ответ дан Chandrajyoti Das 19 August 2018 в 17:31
поделиться

Как упоминалось в принятом ответе

import os
dir = os.path.dirname(__file__)
filename = os.path.join(dir, '/relative/path/to/file/you/want')

, я просто хочу добавить, что

последняя строка не может начинаться с обратного слэша, infact no string should включая обратную косую черту

Это должно быть что-то вроде

import os
dir = os.path.dirname(__file__)
filename = os.path.join(dir, 'relative','path','to','file','you','want')

. В некоторых случаях принятый ответ может вводить в заблуждение, обратитесь к this link для деталей

34
ответ дан Community 19 August 2018 в 17:31
поделиться
  • 1
    Да, используя os.path.join, лучше, потому что он соединяет их с разделителем OS-специфики. – Farshid T 4 September 2016 в 09:16
  • 2
    '/relative/path...' не является относительным путем. Это намеренно? – steveire 13 February 2018 в 13:24
  • 3
    Да, это часть того, что я указывал. – Ahmed 26 April 2018 в 10:51
  • 4
    Этот ответ теперь устарел, так как верхний ответ был отредактирован, чтобы использовать правильный относительный путь в os.path.join(). Остается предпочтение использовать отдельные строки для каждого элемента пути по сравнению с жесткой кодировкой разделителя путей. – Martijn Pieters♦ 12 May 2018 в 18:57

Рассмотрим мой код:

import os


def readFile(filename):
    filehandle = open(filename)
    print filehandle.read()
    filehandle.close()



fileDir = os.path.dirname(os.path.realpath('__file__'))
print fileDir

#For accessing the file in the same folder
filename = "same.txt"
readFile(filename)

#For accessing the file in a folder contained in the current folder
filename = os.path.join(fileDir, 'Folder1.1/same.txt')
readFile(filename)

#For accessing the file in the parent folder of the current folder
filename = os.path.join(fileDir, '../same.txt')
readFile(filename)

#For accessing the file inside a sibling folder.
filename = os.path.join(fileDir, '../Folder2/same.txt')
filename = os.path.abspath(os.path.realpath(filename))
print filename
readFile(filename)
11
ответ дан Fahad Haleem 19 August 2018 в 17:31
поделиться

Альтернатива, которая работает для меня:

this_dir = os.path.dirname(__file__) 
filename = os.path.realpath("{0}/relative/file.path".format(this_dir))
2
ответ дан J0hnG4lt 19 August 2018 в 17:31
поделиться

Я не уверен, что это относится к некоторым из старых версий, но я считаю, что Python 3.3 имеет поддержку родного пути.

Например, следующий код должен создать текстовый файл в той же папке как скрипт python:

open("text_file_name.txt", "w+t")

(обратите внимание, что в начале это не должно быть прямой или обратной косой черты, если это относительный путь)

-2
ответ дан Samy Bencherif 19 August 2018 в 17:31
поделиться

См. sys.path . Инициализированный при запуске программы, первым элементом этого списка, путь [0], является каталог, содержащий скрипт, который использовался для вызова интерпретатора Python.

Используйте этот путь в качестве корневой папки, из которой вы применяете свой относительный путь

>>> import sys
>>> import os.path
>>> sys.path[0]
'C:\\Python25\\Lib\\idlelib'
>>> os.path.relpath(sys.path[0], "path_to_libs") # if you have python 2.6
>>> os.path.join(sys.path[0], "path_to_libs")
'C:\\Python25\\Lib\\idlelib\\path_to_libs'
10
ответ дан Tom Leys 19 August 2018 в 17:31
поделиться
  • 1
    Это не обязательно так. Обычно sys.path [0] - это пустая строка или точка, которая является относительным путем к текущему каталогу. Если вы хотите использовать текущий каталог, используйте os.getcwd. – Jason Baker 27 May 2009 в 22:54
  • 2
    Оригинальный плакат прокомментировал, что текущий рабочий каталог является неправильным местом для определения относительного пути. Вы правильно говорите, что sys.path [0] не всегда действителен. – Tom Leys 28 May 2009 в 01:56
  • 3
    Нет, sys.path[0] не всегда устанавливается в родительский каталог. Код Python может быть вызван с помощью -c или -m или через встроенный интерпретатор, и в этот момент sys.path[0] устанавливается совсем другое. – Martijn Pieters♦ 12 May 2018 в 18:58

вам нужно os.path.realpath (образец ниже добавляет родительский каталог к ​​вашему пути)

import sys,os
sys.path.append(os.path.realpath('..'))
51
ответ дан user989762 19 August 2018 в 17:31
поделиться
  • 1
    os.path.dirname(__file__) дал мне пустую строку. Это сработало отлично. – Darragh Enright 21 February 2014 в 12:51
  • 2
    Кажется, это дает родительскому каталогу, из которого запускается скрипт, а не по месту расположения скрипта. – Coquelicot 17 July 2017 в 03:50
  • 3
    os.path.realpath('..') предоставляет родительский каталог текущего рабочего каталога . Обычно не , что вы хотите. – Martijn Pieters♦ 12 May 2018 в 18:55
  • 4
    @DarraghEnright: Это происходит только в среде упаковки Python-script-to-exe. Это одно из редких исключений, в которых альтернатива будет полагаться на текущий рабочий каталог. – Martijn Pieters♦ 12 May 2018 в 18:56

Что сработало для меня, это использовать sys.path.insert. Затем я указал каталог, в котором мне нужно было идти. Например, мне просто нужно было перейти в один каталог.

import sys
sys.path.insert(0, '../')
1
ответ дан Whitecat 19 August 2018 в 17:31
поделиться
  • 1
    Это зависит от текущего рабочего каталога, который может радикально отличаться от того, что вы действительно хотите. – Martijn Pieters♦ 12 May 2018 в 19:06

Сейчас 2018, и Python уже давно эволюционировали __future__. Итак, как насчет использования удивительного pathlib , следующего с Python 3.4, для выполнения задачи вместо того, чтобы бороться с os, os.path, glob, shutil и т. Д.

Итак, у нас есть 3 пути (возможно, дублируется):

  • mod_path: это путь к простейшему вспомогательному скрипту
  • src_path: содержит пару файлов шаблонов , ожидающих копирования.
  • cwd: текущий каталог , назначение этого шаблона файлов.

, и проблема в том, что у нас нет полного пути к src_path, только знаете, что это относительный путь к mod_path.

Теперь давайте решим это с удивительным pathlib :

# Hope you don't be imprisoned by legacy Python code :)
from pathlib import Path

# `cwd`: current directory is straightforward
cwd = Path.cwd()

# `mod_path`: According to the accepted answer and combine with future power
# if we are in the `helper_script.py`
mod_path = Path(__file__).parent
# OR if we are `import helper_script`
mod_path = Path(helper_script.__file__).parent

# `src_path`: with the future power, it's just so straightforward
relative_path_1 = 'same/parent/with/helper/script/'
relative_path_2 = '../../or/any/level/up/'
src_path_1 = (mod_path / relative_path_1).resolve()
src_path_2 = (mod_path / relative_path_2).resolve()

В будущем это просто так просто. : D


Кроме того, мы можем выбирать и проверять и копировать / перемещать эти файлы шаблонов с помощью pathlib :

if src_path != cwd:
    # When we have different types of files in the `src_path`
    for template_path in src_path.glob('*.ini'):
        fname = template_path.name
        target = cwd / fname
        if not target.exists():
            # This is the COPY action
            with target.open(mode='wb') as fd:
                fd.write(template_path.read_bytes())
            # If we want MOVE action, we could use:
            # template_path.replace(target)
2
ответ дан YaOzI 19 August 2018 в 17:31
поделиться
Другие вопросы по тегам:

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