Если общедоступный API не использует аутентификации и авторизации, Вы неспособны управлять ее использованием (кроме подобных брандмауэру функций как диапазоны IP).
перенаправление Капчи А действительно не поможет Вам: Вы теряете возможность беспрепятственно использовать API в Вашем приложении: С простым нажимают на "developer tools" в браузере, все в состоянии назвать его в байте для байта идентичным путем как тогда, когда используется из Вашего приложения.
, Скорее всего, самое легкое решение состоит в том, чтобы создать своего рода auth& автор: Преследование решения для неразрешимой проблемы обеспечения чего-то, что по определению не защищается, будет стоить Вам большого количества времени руды, головных болей и дыр в системе безопасности, чем просто делать правильно его.
Это потому, что «кодовая страница» cmd отличается от «mbcs» системы. Хотя вы изменили "кодовую страницу", python (фактически, Windows) все еще думает, что ваши "mbcs" не меняются.
Вы хотите, чтобы Python кодировал в UTF-8?
>>>print u'ëèæîð'.encode('utf-8')
ëèæîð
Python будет не распознавать cp65001 как UTF-8.
Несколько комментариев: вы, вероятно, неправильно написали encodig
и .code
. Вот мой прогон вашего примера.
C:\>chcp 65001
Active code page: 65001
C:\>\python25\python
...
>>> import sys
>>> sys.stdin.encoding
'cp65001'
>>> s=u'\u0065\u0066'
>>> s
u'ef'
>>> s.encode(sys.stdin.encoding)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
LookupError: unknown encoding: cp65001
>>>
Вывод - cp65001
не является известной кодировкой для python. Попробуйте "UTF-16" или что-то подобное.
У меня тоже была эта досадная проблема, и я ненавидел невозможность запускать мои сценарии с поддержкой Unicode в MS Windows так же, как и в Linux. Итак, мне удалось найти обходной путь.
Возьмите этот скрипт (скажем, uniconsole.py
в ваших пакетах сайта или что-то в этом роде):
import sys, os
if sys.platform == "win32":
class UniStream(object):
__slots__= ("fileno", "softspace",)
def __init__(self, fileobject):
self.fileno = fileobject.fileno()
self.softspace = False
def write(self, text):
os.write(self.fileno, text.encode("utf_8") if isinstance(text, unicode) else text)
sys.stdout = UniStream(sys.stdout)
sys.stderr = UniStream(sys.stderr)
Кажется, это помогает обойти ошибку python ( или ошибка консоли unicode win32, что угодно). Затем я добавил все связанные сценарии:
try:
import uniconsole
except ImportError:
sys.exc_clear() # could be just pass, of course
else:
del uniconsole # reduce pollution, not needed anymore
Наконец, я просто запускаю свои сценарии по мере необходимости в консоли, где запущен chcp 65001
и используется шрифт Lucida Console
. (Как бы мне хотелось, чтобы вместо него можно было использовать DejaVu Sans Mono
… но взлом реестра и выбор его в качестве шрифта консоли вернется к растровому шрифту.)
Это быстро и грязно ] stdout
и stderr
замена, а также не обрабатывает ошибки, связанные с raw_input
(очевидно, поскольку он вообще не затрагивает sys.stdin
). И, кстати, я добавил псевдоним cp65001
для utf_8
в файл encodings \ aliases.py
стандартной библиотеки.
Вот как переименовать cp65001
в UTF-8 без изменения encodings\aliases. py
:
import codecs
codecs.register(lambda name: codecs.lookup('utf-8') if name == 'cp65001' else None)
(ИМХО, не обращайте внимания на глупости о том, что cp65001
не идентичен UTF-8 на http://bugs.python.org/issue6058#msg97731 . Так и должно быть, даже если кодек Microsoft имеет некоторые незначительные ошибки.)
Вот некоторый код (написанный для Tahoe-LAFS, tahoe-lafs.org), который заставляет консольный вывод работать независимо от кодовой страницы chcp
, а также читает Unicode аргументы командной строки. Заслуга Майкла Каплана за идею этого решения. Если перенаправить stdout или stderr, то будет выводиться UTF-8. Если вам нужен знак порядка байтов, вам нужно будет написать его явно.
[Edit: Эта версия использует WriteConsoleW
вместо флага _O_U8TEXT
в библиотеке времени выполнения MSVC, что является ошибкой. WriteConsoleW
также глючит относительно документации MS, но в меньшей степени.]
import sys
if sys.platform == "win32":
import codecs
from ctypes import WINFUNCTYPE, windll, POINTER, byref, c_int
from ctypes.wintypes import BOOL, HANDLE, DWORD, LPWSTR, LPCWSTR, LPVOID
original_stderr = sys.stderr
# If any exception occurs in this code, we'll probably try to print it on stderr,
# which makes for frustrating debugging if stderr is directed to our wrapper.
# So be paranoid about catching errors and reporting them to original_stderr,
# so that we can at least see them.
def _complain(message):
print >>original_stderr, message if isinstance(message, str) else repr(message)
# Work around <http://bugs.python.org/issue6058>.
codecs.register(lambda name: codecs.lookup('utf-8') if name == 'cp65001' else None)
# Make Unicode console output work independently of the current code page.
# This also fixes <http://bugs.python.org/issue1602>.
# Credit to Michael Kaplan <http://www.siao2.com/2010/04/07/9989346.aspx>
# and TZOmegaTZIOY
# <http://stackoverflow.com/questions/878972/windows-cmd-encoding-change-causes-python-crash/1432462#1432462>.
try:
# <http://msdn.microsoft.com/en-us/library/ms683231(VS.85).aspx>
# HANDLE WINAPI GetStdHandle(DWORD nStdHandle);
# returns INVALID_HANDLE_VALUE, NULL, or a valid handle
#
# <http://msdn.microsoft.com/en-us/library/aa364960(VS.85).aspx>
# DWORD WINAPI GetFileType(DWORD hFile);
#
# <http://msdn.microsoft.com/en-us/library/ms683167(VS.85).aspx>
# BOOL WINAPI GetConsoleMode(HANDLE hConsole, LPDWORD lpMode);
GetStdHandle = WINFUNCTYPE(HANDLE, DWORD)(("GetStdHandle", windll.kernel32))
STD_OUTPUT_HANDLE = DWORD(-11)
STD_ERROR_HANDLE = DWORD(-12)
GetFileType = WINFUNCTYPE(DWORD, DWORD)(("GetFileType", windll.kernel32))
FILE_TYPE_CHAR = 0x0002
FILE_TYPE_REMOTE = 0x8000
GetConsoleMode = WINFUNCTYPE(BOOL, HANDLE, POINTER(DWORD))(("GetConsoleMode", windll.kernel32))
INVALID_HANDLE_VALUE = DWORD(-1).value
def not_a_console(handle):
if handle == INVALID_HANDLE_VALUE or handle is None:
return True
return ((GetFileType(handle) & ~FILE_TYPE_REMOTE) != FILE_TYPE_CHAR
or GetConsoleMode(handle, byref(DWORD())) == 0)
old_stdout_fileno = None
old_stderr_fileno = None
if hasattr(sys.stdout, 'fileno'):
old_stdout_fileno = sys.stdout.fileno()
if hasattr(sys.stderr, 'fileno'):
old_stderr_fileno = sys.stderr.fileno()
STDOUT_FILENO = 1
STDERR_FILENO = 2
real_stdout = (old_stdout_fileno == STDOUT_FILENO)
real_stderr = (old_stderr_fileno == STDERR_FILENO)
if real_stdout:
hStdout = GetStdHandle(STD_OUTPUT_HANDLE)
if not_a_console(hStdout):
real_stdout = False
if real_stderr:
hStderr = GetStdHandle(STD_ERROR_HANDLE)
if not_a_console(hStderr):
real_stderr = False
if real_stdout or real_stderr:
# BOOL WINAPI WriteConsoleW(HANDLE hOutput, LPWSTR lpBuffer, DWORD nChars,
# LPDWORD lpCharsWritten, LPVOID lpReserved);
WriteConsoleW = WINFUNCTYPE(BOOL, HANDLE, LPWSTR, DWORD, POINTER(DWORD), LPVOID)(("WriteConsoleW", windll.kernel32))
class UnicodeOutput:
def __init__(self, hConsole, stream, fileno, name):
self._hConsole = hConsole
self._stream = stream
self._fileno = fileno
self.closed = False
self.softspace = False
self.mode = 'w'
self.encoding = 'utf-8'
self.name = name
self.flush()
def isatty(self):
return False
def close(self):
# don't really close the handle, that would only cause problems
self.closed = True
def fileno(self):
return self._fileno
def flush(self):
if self._hConsole is None:
try:
self._stream.flush()
except Exception as e:
_complain("%s.flush: %r from %r" % (self.name, e, self._stream))
raise
def write(self, text):
try:
if self._hConsole is None:
if isinstance(text, unicode):
text = text.encode('utf-8')
self._stream.write(text)
else:
if not isinstance(text, unicode):
text = str(text).decode('utf-8')
remaining = len(text)
while remaining:
n = DWORD(0)
# There is a shorter-than-documented limitation on the
# length of the string passed to WriteConsoleW (see
# <http://tahoe-lafs.org/trac/tahoe-lafs/ticket/1232>.
retval = WriteConsoleW(self._hConsole, text, min(remaining, 10000), byref(n), None)
if retval == 0 or n.value == 0:
raise IOError("WriteConsoleW returned %r, n.value = %r" % (retval, n.value))
remaining -= n.value
if not remaining:
break
text = text[n.value:]
except Exception as e:
_complain("%s.write: %r" % (self.name, e))
raise
def writelines(self, lines):
try:
for line in lines:
self.write(line)
except Exception as e:
_complain("%s.writelines: %r" % (self.name, e))
raise
if real_stdout:
sys.stdout = UnicodeOutput(hStdout, None, STDOUT_FILENO, '<Unicode console stdout>')
else:
sys.stdout = UnicodeOutput(None, sys.stdout, old_stdout_fileno, '<Unicode redirected stdout>')
if real_stderr:
sys.stderr = UnicodeOutput(hStderr, None, STDERR_FILENO, '<Unicode console stderr>')
else:
sys.stderr = UnicodeOutput(None, sys.stderr, old_stderr_fileno, '<Unicode redirected stderr>')
except Exception as e:
_complain("exception %r while fixing up sys.stdout and sys.stderr" % (e,))
# While we're at it, let's unmangle the command-line arguments:
# This works around <http://bugs.python.org/issue2128>.
GetCommandLineW = WINFUNCTYPE(LPWSTR)(("GetCommandLineW", windll.kernel32))
CommandLineToArgvW = WINFUNCTYPE(POINTER(LPWSTR), LPCWSTR, POINTER(c_int))(("CommandLineToArgvW", windll.shell32))
argc = c_int(0)
argv_unicode = CommandLineToArgvW(GetCommandLineW(), byref(argc))
argv = [argv_unicode[i].encode('utf-8') for i in xrange(0, argc.value)]
if not hasattr(sys, 'frozen'):
# If this is an executable produced by py2exe or bbfreeze, then it will
# have been invoked directly. Otherwise, unicode_argv[0] is the Python
# interpreter, so skip that.
argv = argv[1:]
# Also skip option arguments to the Python interpreter.
while len(argv) > 0:
arg = argv[0]
if not arg.startswith(u"-") or arg == u"-":
break
argv = argv[1:]
if arg == u'-m':
# sys.argv[0] should really be the absolute path of the module source,
# but never mind
break
if arg == u'-c':
argv[0] = u'-c'
break
# if you like:
sys.argv = argv
Наконец, можно удовлетворить желание ΤΖΩΤΖΙΟΥ использовать для консоли DejaVu Sans Mono, который, как я согласен, является отличным шрифтом.
Вы можете найти информацию о требованиях к шрифтам и о том, как добавлять новые шрифты для консоли windows в 'Necessary criteria for fonts to be available in a command window' Microsoft KB
Но в основном, на Vista (возможно, и на Win7):
HKEY_LOCAL_MACHINE_SOFTWARE\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont
, установите "0"
на "DejaVu Sans Mono"
; HKEY_CURRENT_USER\Console
, установите "FaceName"
в "DejaVu Sans Mono"
. На XP проверьте тему "Изменение шрифтов командной строки?" на форумах LockerGnome.