Как я реализую __ getattribute __ без ошибки бесконечной рекурсии?

Предупреждение: mysql_connect (): доступ запрещен для имени пользователя '@' host '

Это предупреждение появляется при подключении к серверу MySQL / MariaDB с недопустимыми или отсутствующими учетными данными (имя пользователя / пароль). Таким образом, это обычно не проблема с кодом, а проблема конфигурации сервера.

  • См. Справочную страницу в mysql_connect("localhost", "user", "pw") для примеров.

  • Убедитесь, что вы действительно использовали кнопки $username и $password.

    • Необычно, что вы получаете доступ без пароля - вот что произошло, когда Предупреждение: сказано (using password: NO).
    • Только локальный тестовый сервер обычно позволяет подключаться с именем пользователя root, без пароля и с именем базы данных test.

    • Вы можете проверить, действительно ли они исправлены с помощью клиента командной строки:
      mysql --user="username" --password="password" testdb

    • Имя пользователя и пароль с учетом регистра и пробел не игнорируется. Если ваш пароль содержит метасимволы, такие как $, откройте их или поместите пароль в одиночные кавычки .

    • Большинство хостинг-провайдеров предопределяют учетные записи mysql в отношении учетной записи пользователя unix (иногда просто префиксы или дополнительные числовые суффиксы). См. Документы для шаблона или документации, а также CPanel или любой другой интерфейс для установки пароля.

    • См. Руководство по MySQL в Добавление учетных записей пользователей с помощью командной строки. При подключении к администратору вы можете выдать запрос, например:
      CREATE USER 'username'@'localhost' IDENTIFIED BY 'newpassword';

    • Или использовать Администратор или [ 1137] WorkBench или любой другой графический инструмент для создания, проверки или исправления данных учетной записи.

    • Если вы не можете исправить свои учетные данные, тогда запрос в Интернете «пожалуйста, помогите» не будет иметь никакого эффекта. Только у вас и вашего хостинг-провайдера есть разрешения и достаточный доступ для диагностики и исправления.

  • Убедитесь, что вы могли достигнуть сервера базы данных, используя имя хоста, указанное вашим провайдером:
    ping dbserver.hoster.example.net

      ]
    • Проверьте это с консоли SSH непосредственно на своем веб-сервере. Тестирование с вашего локального клиента разработки на ваш хостинг-сервер редко имеет смысл.

    • Часто вы просто хотите, чтобы имя сервера было "localhost", которое обычно использует локальный именованный сокет, когда он доступен. В других случаях вы можете попробовать "127.0.0.1" как резерв.

    • Если ваш сервер MySQL / MariaDB прослушивает другой порт, используйте "servername:3306".

    • Если это не удается, тогда есть проблема с брандмауэром.

  • При использовании констант , таких как, например, [11144]. DB_USER или DB_PASSWORD, убедитесь, что они на самом деле определены .

    • Если вы получите "Warning: Access defined for 'DB_USER'@'host'" и "Notice: use of undefined constant 'DB_PASS'", то это ваша проблема.

    • Убедитесь, что ваш, например, xy/db-config.php был фактически включен и что угодно.

  • Проверьте правильность установки GRANT разрешений .

    • Недостаточно иметь пару username + password.

    • Каждая учетная запись MySQL / MariaDB может иметь прикрепленный набор разрешений.

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

    • Предупреждение «Доступ запрещен» может также отображаться для вызовов mysql_query , если у вас нет прав на SELECT из определенной таблицы или INSERT / UPDATE, и чаще всего DELETE.

    • Вы можете адаптировать разрешения учетной записи при подключении к каждому клиенту командной строки с помощью учетной записи администратора с запросом типа:
      GRANT ALL ON yourdb.* TO 'username'@'localhost';

  • Если предупреждение появляется сначала с помощью Warning: mysql_query(): Access denied for user ''@'localhost', тогда у вас может быть php.ini-preconfigured учетной записи / пароля .

    • Убедитесь, что mysql.default_user= и mysql.default_password= имеют значимые значения.

    • Часто это конфигурация провайдера. Поэтому обратитесь к их поддержке несоответствий.

  • Найдите документацию вашего хостинг-провайдера:

  • Обратите внимание, что вы также можете исчерпать доступный пул соединений . Вы получите доступ к запрещенным предупреждениям для слишком большого количества параллельных подключений.

  • Ваша версия клиента libmysql может быть несовместимой с сервер базы данных. Обычно MySQL и MariaDB-серверы можно получить с помощью PHP, скомпилированных в драйвере. Если у вас есть пользовательская настройка или устаревшая версия PHP, а также гораздо более новый сервер базы данных или значительно устаревший - тогда несоответствие версии может препятствовать подключению. (Нет, вам нужно исследовать себя. Никто не может угадать вашу настройку).

Дополнительные ссылки:

Кстати, вы, вероятно, больше не хотите использовать функции mysql_* [1156 ]. Новички часто мигрируют в mysqli , что, однако, так же утомительно. Вместо этого прочитайте в PDO и подготовленные утверждения .
$db = new PDO("mysql:host=localhost;dbname=testdb", "username", "password");

blockquote>

89
задан user2357112 supports Monica 28 December 2017 в 23:18
поделиться

4 ответа

Вы получаете ошибку рекурсии, потому что Ваша попытка получить доступ эти self.__dict__ атрибут в __getattribute__ вызывает Ваш __getattribute__ снова. Если Вы используете object __getattribute__ вместо этого, это работает:

class D(object):
    def __init__(self):
        self.test=20
        self.test2=21
    def __getattribute__(self,name):
        if name=='test':
            return 0.
        else:
            return object.__getattribute__(self, name)

Это работает, потому что object (в этом примере) базовый класс. Путем вызова базовой версии __getattribute__ Вы избегаете рекурсивного ада, в котором Вы были прежде.

Ipython производят с кодом в foo.py:

In [1]: from foo import *

In [2]: d = D()

In [3]: d.test
Out[3]: 0.0

In [4]: d.test2
Out[4]: 21

Обновление:

существует, что-то в разделе назвало [еще 1110] доступ атрибута для модернизированных классов в текущей документации, где они рекомендуют делать точно это для предотвращения бесконечной рекурсии.

115
ответ дан user2357112 supports Monica 24 November 2019 в 07:17
поделиться

На самом деле я полагаю, что Вы хотите использовать __getattr__ специальный метод вместо этого.

Кавычка из документов Python:

__getattr__( self, name)

Названный, когда поиск атрибута не нашел атрибут в обычных местах (т.е. это не атрибут экземпляра, и при этом это не найдено в дереве класса для сам). имя является названием атрибута. Этот метод должен возвратить (вычисленное) значение атрибута или повысить исключение AttributeError.
Примечание, которое, если атрибут найден через нормальный механизм, __getattr__(), не называют. (Это - намеренная асимметрия между __getattr__() и __setattr__().) Это сделано и по причинам эффективности и потому что иначе __setattr__() не имел бы никакого способа получить доступ к другим атрибутам экземпляра. Обратите внимание, что, по крайней мере, например, переменные, можно фальсифицировать полный контроль, не вставляя значений в словарь атрибута экземпляра (но вместо этого вставляя их в другой объект). Посмотрите __getattribute__() метод ниже для способа на самом деле получить полный контроль в модернизированных классах.

Примечание: для этого для работы экземпляр должен не , имеют test атрибут, таким образом, строка self.test=20 должна быть удалена.

24
ответ дан tzot 24 November 2019 в 07:17
поделиться

ссылка языка Python:

для предотвращения бесконечной рекурсии в этом методе, его реализация должна всегда называть метод базового класса с тем же именем для доступа к любым атрибутам, в которых это нуждается, например, object.__getattribute__(self, name).

Значение:

def __getattribute__(self,name):
    ...
        return self.__dict__[name]

Вы призываете к атрибуту, названному __dict__. Поскольку это - атрибут, __getattribute__ назван в поисках __dict__, который звонит __getattribute__, который звонит..., yada yada yada

return  object.__getattribute__(self, name)

Используя базовые классы __getattribute__ помогает нахождению реального атрибута.

16
ответ дан Nisse Engström 24 November 2019 в 07:17
поделиться

Вы уверены, что хотите использовать __getattribute__? Чего Вы на самом деле пытаетесь достигнуть?

самый легкий способ сделать, что Вы спрашиваете:

class D(object):
    def __init__(self):
        self.test = 20
        self.test2 = 21

    test = 0

или:

class D(object):
    def __init__(self):
        self.test = 20
        self.test2 = 21

    @property
    def test(self):
        return 0

Редактирование: Обратите внимание, что экземпляр D имел бы различные значения test в каждом случае. В первом случае d.test был бы 20, во втором, которым это будет 0. Я предоставлю Вам право удаваться почему.

Edit2: Greg указал, что пример 2 перестанет работать, потому что свойство только для чтения и __init__, метод пытался установить его на 20. Более полный пример для этого был бы:

class D(object):
    def __init__(self):
        self.test = 20
        self.test2 = 21

    _test = 0

    def get_test(self):
        return self._test

    def set_test(self, value):
        self._test = value

    test = property(get_test, set_test)

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

13
ответ дан warvariuc 24 November 2019 в 07:17
поделиться
Другие вопросы по тегам:

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