Несколько рекомендаций по экранированию специальных символов в операторах SQL.
Не используйте MySQL , это расширение устарело, используйте MySQLi или PDO .
MySQLi
Для ручного экранирования специальных символов в строке вы можете использовать функцию mysqli_real_escape_string .
Пример:
$mysqli = new mysqli( 'host', 'user', 'password', 'database' );
$mysqli->set_charset( 'charset');
$string = $mysqli->real_escape_string( $string );
$mysqli->query( "INSERT INTO table (column) VALUES ('$string')" );
Для автоматического экранирования значений с помощью подготовленных операторов , используйте mysqli_prepare и mysqli_stmt_bind_param , где для соответствующего преобразования должны быть указаны типы для соответствующих переменных связывания:
Пример:
$stmt = $mysqli->prepare( "INSERT INTO table ( column1, column2 ) VALUES (?,?)" );
$stmt->bind_param( "is", $integer, $string );
$stmt->execute();
Независимо от того, используете ли вы подготовленные операторы или mysqli_real_escape_string, вам всегда нужно знать тип входных данных, с которыми вы работаете.
Итак, если вы используете подготовленный оператор, вы должны указать типы переменных для функции mysqli_stmt_bind_param.
И использование mysqli_real_escape_string для, как сказано в названии, означает экранирование специальных символов в строке, поэтому оно не сделает целые числа безопасными. Цель этой функции - предотвратить разрыв строк в операторах SQL и повреждение базы данных, которое она может вызвать. mysqli_real_escape_string - полезная функция при правильном использовании, особенно в сочетании с sprintf.
Пример:
$string = "x' OR name LIKE '%John%";
$integer = '5 OR id != 0';
$query = sprintf( "SELECT id, email, pass, name FROM members WHERE email ='%s' AND id = %d", $mysqli->real_escape_string( $string ), $integer );
echo $query;
// SELECT id, email, pass, name FROM members WHERE email ='x\' OR name LIKE \'%John%' AND id = 5
$integer = '99999999999999999999';
$query = sprintf( "SELECT id, email, pass, name FROM members WHERE email ='%s' AND id = %d", $mysqli->real_escape_string( $string ), $integer );
echo $query;
// SELECT id, email, pass, name FROM members WHERE email ='x\' OR name LIKE \'%John%' AND id = 2147483647
Что происходит, если кто-то передает строку unicode Вашей функции? Или класс, полученный из dict? Или класс, реализовывая подобный dict интерфейс? Следующий код покрывает сначала два случая. При использовании Python 2.6, Вы могли бы хотеть использовать collections.Mapping
вместо dict
согласно ABC PEP.
def value_list(x):
if isinstance(x, dict):
return list(set(x.values()))
elif isinstance(x, basestring):
return [x]
else:
return None
type(dict())
говорит, "делают новый dict, и затем узнают, каков его тип". Это более быстро для высказывания просто "dict". Но если Вы хотите просто проверить тип, более идиоматический путь isinstance(x, dict)
.
Примечание, это isinstance
также включает подклассы (спасибо Dustin):
class D(dict):
pass
d = D()
print("type(d) is dict", type(d) is dict) # -> False
print("isinstance (d, dict)", isinstance(d, dict)) # -> True
встроенные типы в Python создали на имена:
>>> s = "hallo"
>>> type(s) is str
True
>>> s = {}
>>> type(s) is dict
True
btw отмечают эти , оператор. Однако введите проверку (если Вы хотите назвать ее, что), обычно делается путем обертывания определенного для типа теста в попытке - кроме пункта, поскольку это не так тип переменной, это важно, но можно ли сделать определенное что-то с ним или нет.
Я думаю, что пойду для утки, вводящей подход - "если это будет идти как утка, это шарлатаны как утка, это - утка". Таким образом, Вы должны будете не волноваться о том, если строка будет unicode, или ASCII
Вот то, что я сделаю:
In [53]: s='somestring'
In [54]: u=u'someunicodestring'
In [55]: d={}
In [56]: for each in s,u,d:
if hasattr(each, 'keys'):
print list(set(each.values()))
elif hasattr(each, 'lower'):
print [each]
else:
print "error"
....:
....:
['somestring']
[u'someunicodestring']
[]
эксперты здесь могут прокомментировать этот тип использования ducktyping, я использовал его, но был представлен точному понятию позади него в последнее время и очень взволнован по поводу этого. Таким образом, я хотел бы знать - ли это излишество, чтобы сделать.
isinstance предпочтителен по типу, потому что это также оценивает как Верное при сравнении экземпляра объекта с, он - суперкласс, который в основном означает, что у Вас никогда не будет к особому случаю своего старого кода для использования его с подклассами str или dict.
, Например:
>>> class a_dict(dict):
... pass
...
>>> type(a_dict()) == type(dict())
False
>>> isinstance(a_dict(), dict)
True
>>>
, Конечно, могли бы быть ситуации, где Вы не захотите это поведение, но те - †“hopefully†“намного менее распространенный, чем ситуации, где Вы действительно хотите его.
Я думаю, что это могло бы быть предпочтено, чтобы на самом деле сделать
if isinstance(x, str):
do_something_with_a_string(x)
elif isinstance(x, dict):
do_somethting_with_a_dict(x)
else:
raise ValueError
, 2 Альтернативных формы, в зависимости от Вашего кода один или другой, вероятно, считают лучше, чем это даже. Не нужно посмотреть перед прыганием
try:
one, two = tupleOrValue
except TypeError:
one = tupleOrValue
two = None
, другой подход от Guido и является формой перегрузки функции, которая оставляет код более открытым законченный.
Это должно работать - так не, нет ничего неправильно с Вашим кодом. Однако это могло также быть сделано с dict:
{type(str()): do_something_with_a_string,
type(dict()): do_something_with_a_dict}.get(type(x), errorhandler)()
немного более краткий и pythonic разве Вы не сказали бы?
<час>Редактирование.. Учитывая совет Avisser, код также работает как это и выглядит более хорошим:
{str: do_something_with_a_string,
dict: do_something_with_a_dict}.get(type(x), errorhandler)()
Я использовал другой подход:
from inspect import getmro
if (type([]) in getmro(obj.__class__)):
# This is a list, or a subclass of...
elif (type{}) in getmro(obj.__class__)):
# This one is a dict, or ...
я не могу помнить, почему я использовал это вместо isinstance, хотя...
* sigh *
Нет, аргументы проверки типов в python не нужны. Это никогда необходимо.
Если ваш код принимает либо строку, либо объект dict, ваш дизайн нарушается.
Это происходит из-за того факта, что если вы еще не знаете тип объекта в вашей собственной программе вы уже что-то делаете не так.
Проверка типов вредит повторному использованию кода и снижает производительность. Имея функцию, которая выполняет разные вещи в зависимости от типа передаваемого объекта подвержен ошибкам и имеет поведение, более трудное для понимания и поддержки.
У вас есть следующие более разумные опции:
1) Создайте функцию unique_values
, которая преобразует дикты в уникальные списки значений:
def unique_values(some_dict):
return list(set(some_dict.values()))
Сделайте так, чтобы ваша функция предполагала, что передаваемый аргумент всегда является списком. Таким образом, если вам нужно передать строку в функцию, вы просто делаете:
myfunction([some_string])
Если вам нужно передать это диктом, вы делаете:
myfunction(unique_values(some_dict))
Это ваш лучший вариант, он чистый, легкий для понимания и обслуживания , Кто-нибудь читая код, сразу понимаешь, что происходит, а у тебя нет для проверки типов.
2) Сделайте две функции, одну, которая принимает списки строк и одну, которая принимает
dicts. Вы можете сделать один звонок другого внутри, в наиболее удобном
way ( myfunction_dict
может создать список строк и вызвать myfunction_list
).
В любом случае, не проверять тип . Это совершенно ненужно и имеет только отрицательные стороны. Вместо этого реорганизуйте ваш код так, чтобы вам не нужно было проверять его. Вы получаете только выгоды, как в краткосрочной, так и в долгосрочной перспективе.
You may want to check out typecheck. http://pypi.python.org/pypi/typecheck
Модуль проверки типов для Python
Этот пакет предоставляет мощные средства проверки типов во время выполнения для функций, методов и генераторов Python. Не требуя специального препроцессора или изменений в языке, пакет typecheck позволяет программистам и инженерам по обеспечению качества делать точные утверждения относительно ввода и вывода их кода.