Script vs. Módulo
Aqui está uma explicação. A versão curta é que há uma grande diferença entre executar diretamente um arquivo Python e importá-lo de outro lugar. Apenas saber em que diretório um arquivo está não determina em que pacote o Python pensa que está. Isso depende, adicionalmente, de como você carrega o arquivo no Python (executando ou importando).
Existem duas maneiras de carregar um arquivo Python: como o script de nível superior ou como um módulo. Um arquivo é carregado como o script de nível superior se você o executar diretamente, por exemplo, digitando python myfile.pyna linha de comando. Ele é carregado como um módulo, se você o fizer python -m myfile, ou se for carregado quando uma importinstrução for encontrada dentro de outro arquivo. Só pode haver um script de nível superior por vez; o script de nível superior é o arquivo Python que você executou para começar.
Nomeação
Quando um arquivo é carregado, ele recebe um nome (que é armazenado em seu __name__atributo). Se ele foi carregado como o script de nível superior, seu nome é __main__. Se ele foi carregado como um módulo, seu nome é o nome do arquivo, precedido pelos nomes de quaisquer pacotes / subpacotes dos quais faz parte, separados por pontos.
Por exemplo, no seu exemplo:
package/
__init__.py
subpackage1/
__init__.py
moduleX.py
moduleA.py
se você importou moduleX(nota: importado , não executado diretamente), seu nome seria package.subpackage1.moduleX. Se você importasse moduleA, seu nome seria package.moduleA. No entanto, se você executar diretamente moduleX na linha de comando, seu nome será __main__e, se você executar diretamente moduleAna linha de comando, o nome será __main__. Quando um módulo é executado como o script de nível superior, ele perde seu nome normal e seu nome é __main__.
Acessando um módulo NÃO através do pacote que o contém
Há uma ruga adicional: o nome do módulo depende se foi importado "diretamente" do diretório em que está ou se foi importado por meio de um pacote. Isso só faz diferença se você executar o Python em um diretório e tentar importar um arquivo no mesmo diretório (ou em um subdiretório). Por exemplo, se você iniciar o interpretador Python no diretório package/subpackage1e o fizer import moduleX, o nome de moduleXapenas será moduleX, e não package.subpackage1.moduleX. Isso ocorre porque o Python adiciona o diretório atual ao seu caminho de pesquisa na inicialização; se encontrar o módulo a ser importado no diretório atual, ele não saberá que esse diretório faz parte de um pacote e as informações do pacote não se tornarão parte do nome do módulo.
Um caso especial é se você executar o interpretador interativamente (por exemplo, basta digitar pythone começar a digitar o código Python em tempo real). Nesse caso, o nome dessa sessão interativa é __main__.
Agora, aqui está a coisa crucial para sua mensagem de erro: se o nome de um módulo não tiver pontos, ele não será considerado parte de um pacote . Não importa onde o arquivo está no disco. Tudo o que importa é qual é o nome e depende de como você o carregou.
Agora observe a citação que você incluiu na sua pergunta:
As importações relativas usam o atributo de nome de um módulo para determinar a posição desse módulo na hierarquia de pacotes. Se o nome do módulo não contiver nenhuma informação do pacote (por exemplo, está definido como 'main'), as importações relativas serão resolvidas como se o módulo fosse um módulo de nível superior, independentemente de onde o módulo esteja realmente localizado no sistema de arquivos.
Importações relativas ...
As importações relativas usam o nome do módulo para determinar onde ele está em um pacote. Quando você usa uma importação relativa como from .. import foo, os pontos indicam para aumentar um número de níveis na hierarquia de pacotes. Por exemplo, se o nome do seu módulo atual for package.subpackage1.moduleX, ..moduleAisso significaria package.moduleA. Para que um from .. importtrabalho funcione, o nome do módulo deve ter pelo menos quantos pontos houver na importinstrução.
... são apenas relativos em um pacote
No entanto, se o nome do seu módulo for __main__, ele não será considerado em um pacote. Seu nome não tem pontos e, portanto, você não pode usar from .. importinstruções dentro dele. Se você tentar fazer isso, receberá o erro "importação relativa no pacote".
Os scripts não podem importar relativos
O que você provavelmente fez foi tentar executar algo moduleXsemelhante na linha de comando. Quando você fez isso, seu nome foi definido como __main__, o que significa que as importações relativas falharão, porque seu nome não revela que está em um pacote. Observe que isso também acontecerá se você executar o Python a partir do mesmo diretório em que um módulo está e tentar importar esse módulo, porque, conforme descrito acima, o Python encontrará o módulo no diretório atual "muito cedo" sem perceber que é parte de um pacote.
Lembre-se também de que, quando você executa o intérprete interativo, o "nome" dessa sessão interativa é sempre __main__. Portanto, você não pode fazer importações relativas diretamente de uma sessão interativa . As importações relativas são apenas para uso nos arquivos do módulo.
Duas soluções:
Se você realmente deseja executar moduleXdiretamente, mas ainda assim ele é considerado parte de um pacote, é possível python -m package.subpackage1.moduleX. O -mcomando diz ao Python para carregá-lo como um módulo, não como o script de nível superior.
Ou talvez você realmente não queira executar moduleX , apenas deseja executar outro script, digamos myfile.py, que use funções internas moduleX. Se for esse o caso, coloque myfile.py em outro lugar - não dentro do packagediretório - e execute-o. Se dentro de myfile.pyvocê fizer coisas como from package.moduleA import spam, vai funcionar bem.
Notas
Para qualquer uma dessas soluções, o diretório do pacote ( packageno seu exemplo) deve estar acessível no caminho de pesquisa do módulo Python ( sys.path). Caso contrário, você não poderá usar nada no pacote de maneira confiável.
Desde o Python 2.6, o "nome" do módulo para fins de resolução de pacotes é determinado não apenas por seus __name__atributos, mas também pelo __package__atributo. É por isso que evito usar o símbolo explícito __name__para me referir ao "nome" do módulo. Desde o Python 2.6, o "nome" de um módulo é eficaz __package__ + '.' + __name__, ou apenas __name__se __package__for None.)