Как сделать относительный импорт в Python?

Обновлено 24.2.2017

Раньше я анализировал поддержку использования # define и, как это рекомендуется в некоторых веб-статьях - я попал в определения, которые на Visual C ++ не работали одинаково по сравнению с используемым определением в gcc (например, в интернете это довольно часто называют «прогулкой по MSVC»). Кроме того, вы не сможете легко понять, что происходит за механизмом разработки / макрорасширения - довольно сложно отладить каждое расширение макросов.

Существует несколько способов обойти сложности определения расширения, одним из подходов является включение флага компилятора «/ P» (только для предварительного процесса в файл) - после этого вы можете сравнить, как открывается ваш определение вверх. (Раньше я также активно использовал stringfy operator (#))

Я собрал все полезные определения из нескольких форумов, применил их и закомментировал, что происходит за машиной, вы можете найти весь заголовочный файл в здесь:

https://sourceforge.net/p/testcppreflect/code/HEAD/tree/MacroHelpers.h

Я думал, что это скорее тривиально использовать эти макросы, чтобы включить отражение C ++, но для этого требуется немного больше волшебства.

Я вспомнил рабочий пример кода и поместил его в качестве проекта sourceforge, можно скачать здесь:

https://sourceforge.net/p/testcppreflect/code/HEAD/tree/

Демо-код выглядит следующим образом:

#include "CppReflect.h"
using namespace std;


class Person
{
public:
    REFLECTABLE( Person,
        (CString)   name,
        (int)       age
    )

};

class People
{
public:
    REFLECTABLE( People,
        (CString) groupName,
        (vector)  people
    )
};


void main(void)
{
    People ppl;
    ppl.groupName = "Group1";

    Person p;
    p.name = L"Roger";
    p.age = 37;
    ppl.people.push_back(p);
    p.name = L"Alice";
    p.age = 27;
    ppl.people.push_back( p );
    p.name = L"Cindy";
    p.age = 17;
    ppl.people.push_back( p );

    CStringA xml = ToXML( &ppl );
    CStringW errors;

    People ppl2;

    FromXml( &ppl2, xml, errors );
    CStringA xml2 = ToXML( &ppl2 );
    printf( xml2 );

}

REFLECTABLE define использует имя класса + имя поля с offsetof - для определения того, в каком месте в памяти находится определенное поле. Я попытался подобрать терминологию .NET, насколько это возможно, но C ++ и C # отличаются друг от друга, поэтому это не от 1 до 1. Модель отражения всего C ++ находится в классах TypeInfo и FieldInfo для обеспечения времени, возможно расширить поддержку и метода , но я решил сохранить все просто.

Я использовал парсинг pugi xml для извлечения демонстрационного кода в xml и восстановления его обратно из xml.

Таким образом, вывод, созданный демо-код выглядит следующим образом:



    
        
        
        
    

Также возможно включить любую поддержку 3-го партийного класса / структуры через класс TypeTraits и спецификацию частичного шаблона - определить свой собственный класс TypeTraitsT, в аналогичном способ CString или int - см. пример кода в

https://sourceforge.net/p/testcppreflect/code/HEAD/tree/TypeTraits.h#l65

template <>
class TypeTraitsT : public TypeTraits
{
public:
    virtual CStringW ToString( void* pField )
    { 
        CString* s = (CString*)pField;
        return *s;
    }

    virtual void FromString( void* pField, const wchar_t* value )
    { 
        CString* s = (CString*)pField;
        *s = value;
    }
};

template <>
class TypeTraitsT : public TypeTraits
{
public:
    virtual CStringW ToString( void* pField )
    {
        int* p = (int*) pField;
        return std::to_string(*p).c_str();
    }

    virtual void FromString( void* pField, const wchar_t* value )
    {
        int* p = (int*)pField;
        *p = _wtoi(value);
    }
};

Я полагаю, что только недостатком моей собственной реализации является использование __if_exists - это может быть специфическое расширение компилятора Microsoft. Если кто-то знает, как ходить вокруг, дайте мне знать.

495
задан rypel 16 February 2014 в 15:34
поделиться

3 ответа

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

проблема состоит в том, что Вы выполняете модуль как '__ основной __' путем передачи mod1.py как аргумента интерпретатору.

От PEP 328:

Относительный импорт использует модуль __ имя __ атрибут, чтобы решить что положение модуля в иерархии пакета. Если имя модуля не содержит информации о пакете (например, это установлено на '__ основной __'), тогда, относительный импорт разрешен, как будто модуль был высокоуровневым модулем, независимо от того, где модуль на самом деле расположен в файловой системе.

В Python 2.6, они добавляют способность сослаться на модули относительно основного модуля. PEP 366 описывает изменение.

Обновление : По словам Nick Coghlan, рекомендуемая альтернатива должна выполнить модуль в пакете с помощью переключателя-m.

315
ответ дан John B 16 February 2014 в 15:34
поделиться
main.py
setup.py
app/ ->
    __init__.py
    package_a/ ->
       __init__.py
       module_a.py
    package_b/ ->
       __init__.py
       module_b.py
  1. Вы работаете python main.py.
  2. main.py делает: import app.package_a.module_a
  3. module_a.py делает import app.package_b.module_b

, Кроме того, 2, или 3 мог использовать: from app.package_a import module_a

, Который будет работать, пока Вы имеете app в Вашем PYTHONPATH. main.py мог быть где угодно тогда.

, Таким образом, Вы пишете setup.py для копирования (устанавливают) целый пакет приложения и подпакеты к папкам Python целевой системы, и main.py для предназначения для папок сценария системы.

121
ответ дан nosklo 16 February 2014 в 15:34
поделиться
def import_path(fullpath):
    """ 
    Import a file with full path specification. Allows one to
    import from anywhere, something __import__ does not do. 
    """
    path, filename = os.path.split(fullpath)
    filename, ext = os.path.splitext(filename)
    sys.path.append(path)
    module = __import__(filename)
    reload(module) # Might be out of date
    del sys.path[-1]
    return module

Я использую этот фрагмент для импорта модулей из путей, надеюсь, что это поможет

25
ответ дан 22 November 2019 в 22:35
поделиться
Другие вопросы по тегам:

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