python3 chdir() не работает

Как новичок в python, я решил написать небольшой скрипт python3, который поможет мне переключать каталоги в командной строке (надежный Ubuntu). К сожалению, os.chdir() не работает. Я пытался возиться с ним различными способами, такими как размещение кавычек вокруг пути, удаление ведущей косой черты (что, очевидно, не работает) и даже просто жесткое кодирование, но я не могу заставить его работать - может ли кто-нибудь сказать мне что мне здесь не хватает?

Вызов chdir() происходит ближе к концу — вы также можете увидеть код в github

#!/usr/bin/env python3
# @python3
# @author sabot <[email protected]>
"""Switch directories without wearing out your slash key"""
import sys
import os
import json
import click

__VERSION__ = '0.0.1'

# 3 params are needed for click callback
def show_version(ctx, param, value):
    """Print version information and exit."""
    if not value:
        return
    click.echo('Goto %s' % __VERSION__)
    ctx.exit() # quit the program

def add_entry(dictionary, filepath, path, alias):
    """Add a new path alias."""
    print("Adding alias {} for path {} ".format(alias,path))
    dictionary[alias] = path

    try:
        jsondata = json.dumps(dictionary, sort_keys=True)
        fd = open(filepath, 'w')
        fd.write(jsondata)
        fd.close()
    except Exception as e:
        print('Error writing to dictionary file: ', str(e))
        pass

def get_entries(filename):
    """Get the alias entries in json."""
    returndata = {}
    if os.path.exists(filename) and os.path.getsize(filename) > 0:
        try:
            fd = open(filename, 'r')
            entries = fd.read()
            fd.close()
            returndata = json.loads(entries)

        except Exception as e:
            print('Error reading dictionary file: ', str(e))
            pass
    else:
        print('Dictionary file not found or empty- spawning new one in', filename)
        newfile = open(filename,'w')
        newfile.write('')
        newfile.close()

    return returndata

@click.command()
@click.option('--version', '-v', is_flag=True, is_eager=True,
              help='Print version information and exit.', expose_value=False,
              callback=show_version)
@click.option('--add', '-a', help="Add a new path alias")
@click.option('--target', '-t', help="Alias target path instead of the current directory")
@click.argument('alias', default='currentdir')
@click.pass_context
def goto(ctx, add, alias, target):
    '''Go to any directory in your filesystem''' 

    # load dictionary
    filepath = os.path.join(os.getenv('HOME'), '.g2dict')
    dictionary = get_entries(filepath)

    # add a path alias to the dictionary
    if add:
        if target: # don't use current dir as target
            if not os.path.exists(target):
                print('Target path not found!')
                ctx.exit()
            else:
                add_entry(dictionary, filepath, target, add)
        else: # use current dir as target
            current_dir = os.getcwd()
            add_entry(dictionary, filepath, current_dir, add)

    elif alias != 'currentdir':
        if alias in dictionary:
            entry = dictionary[alias]
            print('jumping to',entry)
            os.chdir(entry)
        elif alias == 'hell':
            print("Could not locate C:\Documents and settings")
        else:
            print("Alias not found in dictionary - did you forget to add it?")

if __name__ == '__main__':
    goto()

person sabot    schedule 19.01.2015    source источник
comment
Вы пытаетесь изменить каталог вашей оболочки? Это не сработает. Дочерний процесс не может этого сделать.   -  person vanza    schedule 20.01.2015


Ответы (2)


Проблема не в Python, проблема в том, что то, что вы пытаетесь сделать, невозможно.

Когда вы запускаете интерпретатор Python (сценарий или интерактивный REPL), вы делаете это из своей «оболочки» (Bash и т. д.). У оболочки есть какой-то рабочий каталог, и он запускает Python в этом же. Когда Python изменяет свой собственный рабочий каталог, это не влияет на родительскую оболочку, и изменения в рабочем каталоге оболочки не влияют на Python после его запуска.

Если вы хотите написать программу, которая изменяет каталог в вашей оболочке, вы должны определить функцию в самой вашей оболочке. Эта функция может вызвать Python, чтобы определить каталог для перехода, например. функция оболочки может быть просто cd $(~/myscript.py), если myscript.py печатает каталог, на который она хочет переключиться.

person John Zwinck    schedule 20.01.2015
comment
Я вижу, это немного разочаровывает, так как я надеялся, что все может произойти через модуль «goto» - я полагаю, что могу превратить его в отдельный словарь и сделать шелл-скрипт «goto», который извлекает из него нужный путь. Спасибо! - person sabot; 20.01.2015
comment
Очень круто, я пока не могу проголосовать, так что вам всем придется обойтись моей искренней благодарностью =) - person sabot; 20.01.2015
comment
@сабот: тоже. это возможно (хотя и не рекомендуется!) - person jfs; 20.01.2015

Вот версия Python 3 решения @ephemient C:

#!/usr/bin/env python3
"""Change parent working directory."""
#XXX DIRTY HACK, DO NOT DO IT
import os
import sys
from subprocess import Popen, PIPE, DEVNULL, STDOUT

gdb_cmd = 'call chdir("{dir}")\ndetach\nquit\n'.format(dir=sys.argv[1])
with Popen(["gdb", "-p", str(os.getppid()), '-q'],
           stdin=PIPE, stdout=DEVNULL, stderr=STDOUT) as p:
    p.communicate(os.fsencode(gdb_cmd))
sys.exit(p.wait())

Пример:

# python3 cd.py /usr/lib && python3 -c 'import os; print(os.getcwd())'
person jfs    schedule 21.01.2015