Уведомления

Группа в Telegram: @pythonsu

#1 Янв. 17, 2022 10:37:22

rmn
Зарегистрирован: 2022-01-17
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

No module named при импорте

Здравствуйте.
Начал изучать.
Не могу победить import, вернее ошибку импорта.

Проект выглядит так:
/project_root
—-settings/
——–config.py
—-db/
——–creator.py

В папке settings лежит файл с настройками. В настройка прописано название БД.
В папке db лежит файл creator.py, который создаёт sqlite базу.

Пытаюсь импортировать config.py в creator.py так:

 from settings import config
Запускаю creator.py в Shell.

Получаю ошибку:
ModuleNotFoundError: No module named ‘settings’

Подскажите пжл, что делаю не так.
Уже и относительные пути все перепробовал и абсолютные. Не видит модуль и всё.

Пробежался скриптом по каталогам. Всё есть.
 cp = (os.path.abspath(os.curdir))
  with os.scandir(cp) as files:
      subdir = [file.name for file in files if file.is_dir()]
  print(subdir)

Если запускать не через shell, то всё прекрасно импортируется.

Офлайн

#2 Янв. 18, 2022 07:55:07

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4121
Репутация: +  251  -
Профиль   Отправить e-mail  

No module named при импорте

rmn
Подскажите пжл, что делаю не так.
Уже и относительные пути все перепробовал и абсолютные.
Тут надо понять что в строке импорта указываются вовсе не пути. Это перечень вложенных пакетов который завершается опционально модулем. Есть вполне определенные правила поиска модулей и пакетов:
https://docs.python.org/3/reference/import.html
Вы, очевидно, не выполняете эти правила.



Отредактировано doza_and (Янв. 18, 2022 07:55:35)

Офлайн

#3 Янв. 18, 2022 08:26:23

rmn
Зарегистрирован: 2022-01-17
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

No module named при импорте

doza_and
Вы, очевидно, не выполняете эти правила.
Спасибо большое.
Да, разобрался уже.
Решил проблему так.
Сначала определил, где выполняется команда:
 curDir = os.getcwd()
Затем, добавил этот путь в систем паз:
 sys.path.append(curDir)
Всё работает.

Много где подобное советуют, но без разжевывания и примеров.
Может пригодится кому.

Офлайн

#4 Янв. 18, 2022 21:12:54

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 8435
Репутация: +  756  -
Профиль   Отправить e-mail  

No module named при импорте

rmn
Затем, добавил этот путь в систем паз:
  
sys.path.append(curDir)
Всё работает.
Много где подобное советуют
Если такое нужно делать, то проект просто как-то неправильно организован. Это костыль, а костыль - это не нога.



Офлайн

#5 Янв. 18, 2022 21:19:58

rmn
Зарегистрирован: 2022-01-17
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

No module named при импорте

py.user.next
Если такое нужно делать, то проект просто как-то неправильно организован. Это костыль, а костыль - это не нога.
Соглашусь пожалуй.
Но.
Я ж учусь только. Да и попробуйте сами сделать как я указал в первом посте. Очень распространенная проблема, судя по поисковой выдаче. Подчеркну, что ошибка возникает лишь при запуске скрипта, содержащего импорты пакетов из других каталогов, в Shell. Проектные пакеты прекрасно всё импортят, независимо от вложенностей и.т.п.

Офлайн

#6 Янв. 19, 2022 02:53:44

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 8435
Репутация: +  756  -
Профиль   Отправить e-mail  

No module named при импорте

rmn
Очень распространенная проблема, судя по поисковой выдаче.
Миллион леммингов не может ошибаться. Ну да. Также можно найти миллион советов в стиле “используй os.getcwd()”. Ты вообще про эту функцию вспоминать не должен никогда. Она вообще очень редко когда тебе понадобится во всём твоём программировании в ближайшие десятки лет и то при работе с каким-то там текущим каталогом в какой-нибудь редкой функции.

Ни переменные среды, ни редактирование путей, - ничего такого там не надо делать. К тому же вся эта фигня вроде ModuleNotFoundError сделана специально, потому что её умные люди делали. А вот то, что ты пытаешься сделать, это как раз делать не надо, потому что один модуль никогда не должен знать что-либо про внутренности другого модуля, в этом вся суть модульности и заключается. Модули если и знают друг про друга вообще, то они общаются максимум через внешние границы, хорошо формализованные.

Каким макаром у тебя модуль db знает имена файлов в модуле settings? А если ты захочешь имя файла поменять внутри модуля settings, ты не сможешь это сделать, потому что сразу сломаются сотни других модулей, потому что ждут от этого модуля того, что у него внутри файл его внутренний как-то там называется? Вот для чего модульность нужна. Ты должен в любой момент поменять имя любого файла в любом модуле и это не должно никого волновать. Все должны продолжать работать исправно. И у них у всех то же самое внутри. Это независимость модулей друг от друга. Поэтому-то они и модули.

rmn
Я ж учусь только.
Ну, кроме питона, программирование ещё есть. И вот это - инфа про модули - это теория программирования. То есть ты и в питоне новичок, и в программировании ты тоже новичок.

Вот в питоне есть понятие “модуль” и есть понятие “пакет”, а в программировании есть понятие “модуль” и всё. Так что что модуль, что пакет из питона - это всё просто модули из программирования. И это надо видеть. И чтобы это видеть, это надо знать. А чтобы это знать, это надо читать целенаправленно. Поэтому когда ты лезешь из одного модуля в другой, надо задаться вопросом “а что я делаю?”.

В пакетном __init__.py файле должны быть все импорты, которые нужны там где-то внутри этого пакета. И никто из пакета не должен вылазить наружу, чтобы что-то там раздобыть. Все обращаются к самому модулю, в котором они находятся, и просят его “дай мне такой-то модуль, чтобы я у него попросил то, что он там может делать”. То есть они с внешним миром общаются через границу модуля, в котором они находятся как части.



Отредактировано py.user.next (Янв. 19, 2022 02:56:40)

Офлайн

#7 Янв. 19, 2022 05:53:59

rmn
Зарегистрирован: 2022-01-17
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

No module named при импорте

py.user.next
Ни переменные среды, ни редактирование путей, - ничего такого там не надо делать.
Если функционал есть, значит он зачем-то нужен, да?
py.user.next
потому что один модуль никогда не должен знать что-либо про внутренности другого модуля
Абсолютно верно. Но только, если это именно модуль, а не пакет. Вобще сложно пока понять на кой чёрт создатели сделали такую универсальность. Каталог может быть модулем, а может пакетом. Лучшее - враг хорошего.
py.user.next
Модули если и знают друг про друга вообще, то они общаются максимум через внешние границы, хорошо формализованные.
Можно пример?
py.user.next
Каким макаром у тебя модуль db знает имена файлов в модуле settings?
Ещё раз. В ПАКЕТЕ settings лежит файл конфигурации. Класс с некими свойствами, в том числе и с названием базы. Которые нужно считывать отовсюду, где нужно.
Что здесь не правильно? Как это противоречит парадигме использования методов и классов из других пакетов? Пока решил использовать configParser, отказался от своей реализации конфигурации.
py.user.next
В пакетном __init__.py файле должны быть все импорты, которые нужны там где-то внутри этого пакета.
За это спасибо. Надо изучить как добавлять. Я то решил, что достаточно пустого файла в любом каталоге, который хочу использовать как пакет.
py.user.next
И никто из пакета не должен вылазить наружу, чтобы что-то там раздобыть. Все обращаются к самому модулю, в котором они находятся, и просят его “дай мне такой-то модуль, чтобы я у него попросил то, что он там может делать”.
Так и намеревался реализовать. Где в моём подходе я неправ? И как бы сделал ты?
py.user.next
миллион советов
Спасибо за развёрнутый ответ. Честно.

Офлайн

#8 Янв. 20, 2022 00:53:27

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 8435
Репутация: +  756  -
Профиль   Отправить e-mail  

No module named при импорте

rmn
Если функционал есть, значит он зачем-то нужен, да?
Не всегда это так. Иногда функционал есть для того, чтобы его проверить. Если он покажет свою нужность и успешность, полезность такую, то его оставят и будут развивать дальше. А если он окажется неиспользуемым, рудиментарным (как хвостик у человека, который ещё есть иногда), то его удалят (пометят как deprecated сначала, а потом и вовсе вырежут из будущих версий, как отвалившуюся сухую ветку у растения, которая когда-то там была зелёной и полной сил).
В контексте питона можно увидеть множество таких примеров, часть из которых всё ещё есть в нём, но уже в дохлом виде, а часть уже вырезана и официально признана удалённой как несостоявшаяся идея. Имменно из-за этого питон и называют многие люди, которые в теме, языком экспериментов, экспериментальным языком. Именно из-за этого он не стандартизировался изначально.
Примеры удалённых частей: int/long (тип int удалён, а long переименован в int); функции range()/filter()/map() (эти функции сначала оставляли и добавляли функции xrange()/itertools.ifilter()/itertools.imap(), а потом удалили из языка функцию range() и функцию xrange() переименовали в функцию range(), также удалили filter() и map(), а функции itertools.ifilter()/itertools.imap() переименовали в filter() и map(), теперь их в itertools нет); то же самое было с input(); а функция print() раньше вообще была оператором print и не имела адреса (то есть её нельзя было передать в другую функцию, как можно сделать сейчас).

Поэтому я тебе и говорю, что мало ли что там есть, есть общепринятые практики, которые используются всеми знающими людьми, и есть, естественно, новичковые потуги, которые тоже распространены среди миллионов новичков и даже массово обсуждаются ими как рабочие способы. У тебя чего-то уникального я не вижу. Ты идёшь, как стандартный новичок, который что-то не знает и начинает цепляться за то, что торчит там перед носом. Ну, как мышка, которая цепляет сыр, прикрепленный к железной такой палочке, с мыслями “вижу сыр! это сыр! это точно сыр, а не что-то другое! да что вы мне говорите! а раз это сыр, то можно съесть сыр, сэр! я умная!”, потом ба-бах! и мышка такая “ой! я что-то не знала… происходит что-то не-то… я не чувсвтую ног… у меня что? у меня что?! сломан позвоночник?! какой ужас… я просто хотела сыру… маленький кусочек… совсем маленький.”. Сдохла твоя мышка, вот в чём прикол.

rmn
Абсолютно верно. Но только, если это именно модуль, а не пакет.
Нет такого понятия “пакет”. Это внутреннее понятие из языка программирования. Сначала оно в Java было, потом в Python переехало. Конечно, оно не в Java началось, но так как Java - объектно-ориентированный язык, а Python хотели сделать объектно-ориентированным, то и понятие пакета в Python'е тоже воспроизвели. Хотя в разных языках эти пакетные системы, где они есть вообще, по-разному устроены. То есть, я думаю, они хотели, как в Java, но чтобы не как в Java, а чтобы по-своему как-то сделать их. Так-то пакетные системы известны ещё до ООП, но они не были тогда хорошо и чётко формализованы.
Пакет в питоне - это модуль в программировании.
Модуль в питоне - это модуль в программировании.
Объект в питоне - это модуль в программировании.
Функция в питоне - это модуль в программировании.
Это всё модули. А для модулей есть правила для модулей. И вот по этим правилам один модуль внутрь другого модуля лезть не должен. Существует понятие модульной когезии и модульного зацепления. Если между модулями сильное зацепление, то изменение (редактирование) одного модуля приводит к изменению (редактированию) другого модуля.
То есть иными словами, тебе нужно поменять на машине колесо, тогда ты просто берёшь и откручиваешь старое колесо и прикручиваешь новое колесо на место старого колеса. Потому что колесо - это модуль, ось - это модуль. А вот если ты для смены колеса должен сначала сменить двигатель, потому что двигатель зависит от шины в этом колесе (ну, каким-то макаром), то это уже что-то не то происходит. Какой-то дурак этот двигатель сделал не модулем с сильной когезией и слабым зацеплением, а зацепил этот модуль за другой модуль, причём зацепил ещё за внутренности того модуля, а не за внешнюю часть, - то есть это уже двойная дурость. Если бы двигатель понимал, что колесо слабо прикручено и из-за этого переставал работать, он был бы зацеплен за внешнюю часть модуля, что тоже является не очень умным (да просто тупостью является, ведь перестановка этого двигателя в другую машину потянет следом за собой и перестановку колеса того тоже, ведь двигатель хочет то колесо и прикручено оно ещё должно быть, чтобы он заводился вообще), а тут он с какого-то перепугу знает про шину в колесе.

rmn
на кой чёрт создатели сделали такую универсальность. Каталог может быть модулем, а может пакетом.
Каталог не может быть модулем. Модулем может быть только файл. А каталог может быть каталогом или пакетом. Пакетом он становится, если в нём обнаруживается файл __init__.py .
Это всё понятия питона, не общей теории программирования.
Надеюсь, ты уже начал понимать, что слово “модуль” в одном месте и слово “модуль” в другом месте - это разные понятия, которые означают разные вещи.
Так вот, это очень чудесно устроено, потому что “модуль” и “модуль” могут быть одновременно в одном и том же. При этом первый “модуль” притягивает одни правила к этому, а второй “модуль” притягивает другие правила к этому. Они как будто перпендикулярно друг к другу идут и вообще находятся в разных измерениях, но они одновременно работают.

И вот ты полез из внутренностей одного пакета во внутренности другого пакета. А почему так нельзя делать? Потому что пакеты в теории питона - это модули из общей теории программирования. А по общей теории программирования нельзя ослаблять когезию модулей (из модуля вылазить куда-то наружу и вообще заниматься чем-то посторонним, не относящимся к модулю) и нельзя усиливать зацепление модулей сильнее, чем просто зацепление по простейшим данным, максимально просто передаваемым.

Поэтому тебе и говорят “ты что-то не то делаешь, не трогай этот сыр; да, его можно съесть; да, он вкусный; да, он не отравлен; да, в нём очень много питательных веществ; но его не надо есть; почему? потому что там такая хуйня железная, приделанная к другой хуйне, как раз на который сыр, которая такая на закрученной пружине, и она как ебанёт, когда ты начнёшь его брать, что хорошо если она тебе просто перерубит хвост и ты сможешь ещё съебаться в итоге, но может получиться так, что тебе придётся отгрызать собственную ногу, потому что её зажмёт этой хуйнёй и её никак не вытащишь, а тебе надо будет уходить как-то, а в худшем случае тебя вообще перерубит пополам и, даже если ты выберешься, ты максимум доползёшь до угла и там в норку залезешь и сдохнешь в норке своей тёплой и уютной, если не по пути к ней”.

rmn
py.user.next
Модули если и знают друг про друга вообще, то они общаются максимум через внешние границы, хорошо формализованные.
Можно пример?
Ну, как колесо к оси крепится? На оси есть такие болтики и на колесе есть такие дырочки и к ним гаечки. Вот ось - это модуль, колесо - это модуль. Вот эти болтики на оси - это внешний интерфейс оси. А дырочки на колесе - это внешний интерфейс колеса. Через свои внешние интерфейсы эти два модуля прикрепляются друг к другу. То есть ось не знает про шину в колесе. А колесо не знает, какие там подшипники в оси. Шина - это внутренняя часть модуля, который представлен колесом. А подшипники - это внутренняя часть модуля, который представлен осью. Они внутренние не потому, что их не видно, а они внутрение потому, что их “не видно”. То есть их можно убрать и это ничего не изменит. Вот как колесо крепилось к оси, так оно и будет дальше крепиться к оси как без подшипников в оси, так и без шины на колесе. Как оно было накачанным, так оно и останется накаченным без подшипников в оси. Как ось вращалась, так она и будет вращаться, если с колеса снять шину вообще.

Болтики и гаечки тоже являются модулями, но об этом не будем, чтобы у тебя уши в трубочку совсем уж не завернулись здесь. Сейчас не об этом речь.

Поэтому у пакета в питоне есть интерфейс. И этот интерфейс обеспечивается этим __init__.py . То есть интерфейс либо там находится, либо в каком-то главном файле пакета.
То есть ты импортируешь пакет, он тебе говорит “вот мои болтики”, ты его спрашиваешь “а где твои подшипники?”, а он тебе говорит “а это тебя ебать не должно, это мои внутренние части”. Ты ему говоришь “нет! ты дай мне вот этот подшипник”, а он тебе говорит “да пошёл ты на хуй просто и всё!”.

Это вот говоришь ты
rmn
  
from settings import config
А это вот говорит он
rmn
ModuleNotFoundError: No module named 'settings'

Он тебе может дать подшипники, если в нём описано, как давать эти подшипники наружу. И то это маловероятно, что он так будет делать, потому что очень сложно себе представить, что ось будет каким-то особенным колёсам, не всем подряд, свои подшипники давать покрутить. Зачем?

Обычно интерфейс пакета смотришь так: импортируешь пакет и запускаешь help(имя_пакета). Это если не можешь в документацию залезть и её прочитать. Потому что обычно интерфейс пакета описан в документации к пакету автором пакета. Вот всё, что там видишь, всё твоё. Всё, чего там нет, это всё внутримодульное. Если ты туда всё равно полез и воспользовался, это называется хак. А хак - это не умность, как может показаться, а это тупость. Если у тебя хаки по коду идут, есть подозрение, что ты тупой, ну, или бракодел, барыга-бракодел чаще всего, который побыстрее делает говно какое-нибудь и спихивает людям незнающим, пирожки с котятами, короче. На вкус вроде мясо, а по сути заразная хуйня какая-то. Но его не волнует, он деньги получил. А эти сдохнут - да и хуй с ними.

rmn
Пока решил использовать configParser, отказался от своей реализации конфигурации.
Не, это не ConfigParser, это надо изучить, как это делают другие. Думаю, там settings как раз для этого, просто у тебя не простроена хуйня вся. Скорее всего, вот эта среда что-то делает, а ты этого не делаешь. Она простраивает, а ты нет. Поэтому в ней видно, а у тебя - хуй.

rmn
Я то решил, что достаточно пустого файла в любом каталоге, который хочу использовать как пакет.
Может быть досточно, а может быть недостаточно.
Через help(имя_модуля) проверь, что там доступно.
Потому что интерфейс может быть в главном файле, но этот __init__.py этот интерфейс перетаскивать может (пробрасывать) так, что его будет видно снаружи у этого пакета. Импортирования пакета должно быть достаточно, чтобы увидеть внешний интерфейс этого пакета.

rmn
Где в моём подходе я неправ? И как бы сделал ты?
Сначала почитал бы документацию. Обычно это самая быстрая хуйня. Ты как бы не первый человек, который делает такое приложение, поэтому кто-то уже его делал и кто-то из них его уже сделал и написал документацию, как его делать, чтобы его сделать. То есть документация чаще всего есть, чем её нет. Потом бы запустил help(имя_пакета), потому что там уже физически видно, что доступно. И потом, может быть, я стал бы лазить и выяснять, как они в среде своей это сделали. Но, скорее всего, я бы это бросил и вернулся к документации, потому что что-то пропустил, а это выяснение про эту среду всё равно никак не поможет, потому что не факт, что это лучший способ. Это костылём среды может быть. Да! Бывает такое! Что в средах и других программах бывают костыли, которые перенимешь такой радостный, а потом из-за них у тебя что-нибудь сломается в итоге и в самый неожиданный момент, когда у тебя времени на то, чтобы это исправлять, вообще не будет.
Ну как, знаешь, можно купить с рук очень дешёвый телефон и ходить радоваться, какой хороший телефон, всё работает и практически за бесплатно, а потом полиционер к тебе приходит и говорит “а это не твой телефон, возвращай или будешь укравшим, нам похер кого сажать”. И ты такой “блядь, а у меня там контакты все, настройки, приложения, смски в нём хранятся, потому что на симке не помещаются, и длинные имена на симке не помещаются и всякая хуйня на симке не помещается”. Потом такой “а я на SD-карточку всё перенесу”, а они на нём не поддерживаются, не ты же его покупал, а какой-то крендель, который не умеет телефоны выбирать и читать, что в нём есть и что завтра понадобится, у которого его потом и спиздили аналогичным образом из заднего кармана в итоге, пока он на рынке наклонялся за капустой, которую бабка с картонки продавала. Долбоёб в кубе.

Можешь пробросить интерфейс, конечно, но я думаю, ты обосрёшься. Так как новичок ещё. Ну, всю эту хуйню мне нужно тебе рассказывать, потому что ты всех этих основ не знаешь. Знал бы ты, я бы тебе всё это не рассказывал. А это просто хуйня какая-то, которая с опытом приходит. В двух словах не расскажешь. Это всё нужно попробовать и понять, что хорошо, что плохо, потому что много и всякой фигни в программировании, ну, фуфельной, которая отжила своё, и её тоже надо уметь определять и распознавать, чтобы не пользоваться хрен знает чем, когда это всё идёт в минус, а не нейтрально хотя бы. Хочешь засрать проект какой-нибудь хуетой древней - это запросто. Потом ты узнаешь, что не надо было этого делать, потому что эта хуйня работает плохо, на самом деле, но тогда ты не знал этого, потому что на этой хуйне не написано, что эта хуйня хуёвая. Это надо получить по лбу. Только так это и усваивается, и запоминается.

Вот пример - в питоне пакет logging. Документации написано пиздец, до каждой мелочи, всё отлично, чуть ли не самая лучшая документация к пакету в питоне, всё понятно в ней. А по сути, ну, сам пакет, код пакета, интерфейс пакета, - какая-то параша - “это не создавай! это не открывай! а то сломается всё! делай вот так, только вот так, по-уебански”. Я этим пакетом вооще не пользуюсь, свои логеры делаю. А так, снаружи, кажется, что это гениальная хуйня, она же такая большая. Ну, это чемодан без ручки, который не могут бросить.



Отредактировано py.user.next (Янв. 20, 2022 02:13:20)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version