Форум сайта python.su
Python 2.7
Windows 7
Необходимо запустить внешнюю программу из Python.
Проблема 1. В пути к программе присутствуют русские символы.
Проблема 2. Программе нужно передать параметр-строку, которая представляет собой путь к другой папке (тоже с русскими символами).
Отчаянно гуглил по проблеме, накопал много инфы, пробовал по-всякому. Прошу, помогите её систематизировать и упорядочить, дабы решить проблему.
Что я понял.
1. Исходный код программы следует держать в UTF-8.
Для этого я вначале кода указал
# -*- coding: utf-8 -*-
ur"C:\Директория1\Директория2"
os.system(ur"C:\Директория1\Директория2\Приложение.exe")
# -*- coding: utf-8 -*-
import subprocess
import sys
import codecs
import os
# эту функцию я нагуглил на сайте хабрахабр, вроде она должна решать проблемы с кодировкой
def setup_console(sys_enc="utf-8"):
reload(sys)
try:
# для win32 вызываем системную библиотечную функцию
if sys.platform.startswith("win"):
import ctypes
enc = "cp%d" % ctypes.windll.kernel32.GetOEMCP() #TODO: проверить на win64/python64
else:
# для Linux всё, кажется, есть и так
enc = (sys.stdout.encoding if sys.stdout.isatty() else
sys.stderr.encoding if sys.stderr.isatty() else
sys.getfilesystemencoding() or sys_enc)
# кодировка для sys
sys.setdefaultencoding(sys_enc)
# переопределяем стандартные потоки вывода, если они не перенаправлены
if sys.stdout.isatty() and sys.stdout.encoding != enc:
sys.stdout = codecs.getwriter(enc)(sys.stdout, 'replace')
if sys.stderr.isatty() and sys.stderr.encoding != enc:
sys.stderr = codecs.getwriter(enc)(sys.stderr, 'replace')
except:
pass # Ошибка? Всё равно какая - работаем по-старому...
setup_console()
path = ur"C:\Директория1\Директория2\Приложение.exe"
path = os.path.normpath(path)
os.system("chcp 65001")
os.system(path)
Active code page: 65001Также, если немного поэксперементировать с командой, меняя её, то выводится другое, но похожее сообщение:
The filename, directory name, or volume label syntax is incorrect.
Process finished with exit code 0
The system cannot find the path specifiedПри этом сама команда на 100% верная. Если я её просто копирую из кода и вставляю в консоль она нормально выполняется.
Отредактировано (Сен. 27, 2011 11:54:40)
Офлайн
1 :) Я оч злобный, поэтому указываю - вы пропустили самый главный совет: не делать путей с русскими символами и пробелами. Если есть - переименовать. В питоне это легко побороть, а в других языках проблемы почти непреодолимы.
Офлайн
Моя программа это пакетный перекодировщик книг из fb2 в mobi. Алгоритм её работы заключается в рекурсивном обходе дерева папок с книгами и передаче каждой книги в качестве параметра стороннему перекодировщику fb2->mobi, который не поддерживает пакетный режим. Соответственно мой скрипт это этакая обёртка к нему.
Ладно, допустим можно легко переименовать путь к самой сторонней программе-перекодировщику.
Но вот с параметром, в котором передаётся путь к папке, уже сложнее.
Я скачал кучу книг с торрента, все книги рассортированы по папкам, названия которых представляют собой фамилии авторов, названия жанров.
Мало того, что мне неудобно будет потом работать с этой иерархией, если я всё запишу транслитом, так ещё и поддерживать торрент-раздачу после переименования не получится.
Да, можно создать отдельное дерево папок, не трогая исходное. Но это примитивный вариант, достаточно ёмкий по времени и костыльный.
Как вариант может создавать символьную ссылку с латинским названием на оригинальный файл, работать с ней, а потом питоном переименовывать полученный файл на русское название. Интересный вариант, но, сами понимаете, тоже костыльный.
В питоне это легко побороть, а в других языках проблемы почти непреодолимы.Не понял, что именно в питоне легко побороть?
Офлайн
Легко побороть русские символы в путях. Мне тут не дали закончить. Бороться с консолью не надо.
Сделайте os.system(“some command 1>1 2>2”) и ловите сообщения в файл.
ur“C:\Директория1\Директория2\Приложение.exe” можно заменить на
u“C:/Директория1/Директория2/Приложение.exe” Но это не принципиально.
По поводу юникода - вы правильно поняли. У меня Windows XP и os.system(u“ФФФ.exe”) работает без проблем.
Чего в семерке - не скажу. Поэтому если есть хоть малейшая возможность - не используйте в путях не латиницу.
Для проверки чего получается сделайте
os.system(u"python.exe tie.py ффф.txt")
Отредактировано (Сен. 27, 2011 14:27:22)
Офлайн
ПО поводу пакетной перекодировки: Я не понял зачем эти танцы с бубном
def PathFind(pattr,root="."):
"""аналог find"""
for di,dl,fl in os.walk(root):
for f in glob.fnmatch.filter(fl,pattr):
yield os.path.join(di,f)
Отредактировано (Сен. 27, 2011 14:37:30)
Офлайн
doza_andИзвините, не уловил, что вы имели в виду.
Легко побороть русские символы в путях. Мне тут не дали закончить. Бороться с консолью не надо.
Сделайте os.system(“some command 1>1 2>2”) и ловите сообщения в файл.
ur“C:\Директория1\Директория2\Приложение.exe” можно заменить на
u“ChmmДиректория1/Директория2/Приложение.exe” Но это не принципиально.
По поводу юникода - вы правильно поняли. У меня Windows XP и os.system(u“ФФФ.exe”) работает без проблем.
Чего в семерке - не скажу. Поэтому если есть хоть малейшая возможность - не используйте в путях не латиницу.
Для проверки чего получается сделайте
Код:
os.system(u“python.exe tie.py ффф.txt”)
а из tie.py сохраните в файл командную строку, чтобы разобраться что у вас приходит в cmd
doza_andЧто именно вам не понятно?
ПО поводу пакетной перекодировки: Я не понял зачем эти танцы с бубном
doza_andБоюсь я с генераторами ещё не работал и не совсем понимаю принцип их работы.
У меня этот генератор дает имена - пригодные для выполнения.
doza_andВроде проблемы с обходом дерева папок нет. На каждом шаге я получаю UTF-8 строку, которую надо скормить в качестве параметра сторонней программе.
Может он вам поможет?
Офлайн
Сейчас попытался сделать через костыль: сначала прокидывать симлинк с англопутём на целевой файл с русским путём.
Симлинк прокидываю с помощью функции
win32file.CreateSymbolicLink(temp_file, filename, 1)
Active code page: 65001
Traceback (most recent call last):
File “D:/dev/python/books_converter/book_converter/book_converter.py”, line 77, in <module>
convert_files_from_dir(files)
File “D:/dev/python/books_converter/book_converter/book_converter.py”, line 14, in convert_files_from_dir
win32file.CreateSymbolicLink(temp_file, filename, 1)
pywintypes.error: (1314, ‘CreateSymbolicLink’, ‘\xca\xeb\xe8\xe5\xed\xf2 \xed\xe5 \xee\xe1\xeb\xe0\xe4\xe0\xe5\xf2 \xf2\xf0\xe5\xe1\xf3\xe5\xec\xfb\xec\xe8 \xef\xf0\xe0\xe2\xe0\xec\xe8.’)
Process finished with exit code 1
Офлайн
Пытался декодировать строки в cp866 прежде чем скармливать их функции
win32file.CreateSymbolicLink(temp_file.encode("cp866"), filename.encode("cp866"), 1)
Офлайн
import subprocess
Офлайн
#!/usr/bin/env python
# -*- coding: cp1251 -*-
import subprocess as sp
import os
#sp.call("фыв.exe")
os.system("фыв.exe")
Офлайн