利用pipenv shell切換到虛擬環境時,顯示報錯:AttributeError: 'module' object has no attribute 'run'html
能夠看到是d:\program\python34\lib\site-packages\pipenv\shells.py文件的第62行報錯了,提示模塊沒有run的屬性,因而就跑到該文件的第62行去看python
選中run,CTRL+B發現能看到源碼,源碼以下:shell
if sys.version_info >= (3, 6): # Nearly same args as Popen.__init__ except for timeout, input, and check def run(args: _CMD, timeout: Optional[float] = ..., input: Optional[_TXT] = ..., check: bool = ..., bufsize: int = ..., executable: _PATH = ..., stdin: _FILE = ..., stdout: _FILE = ..., stderr: _FILE = ..., preexec_fn: Callable[[], Any] = ..., close_fds: bool = ..., shell: bool = ..., cwd: Optional[_PATH] = ..., env: Optional[_ENV] = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Any = ..., *, encoding: Optional[str] = ..., errors: Optional[str] = ...) -> CompletedProcess: ... else: # Nearly same args as Popen.__init__ except for timeout, input, and check def run(args: _CMD, timeout: Optional[float] = ..., input: Optional[_TXT] = ..., check: bool = ..., bufsize: int = ..., executable: _PATH = ..., stdin: _FILE = ..., stdout: _FILE = ..., stderr: _FILE = ..., preexec_fn: Callable[[], Any] = ..., close_fds: bool = ..., shell: bool = ..., cwd: Optional[_PATH] = ..., env: Optional[_ENV] = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Any = ...) -> CompletedProcess: ...
可是請看第一行 if sys.version_info >= (3, 6): ,咱們姑且猜想一下,這個3.6就是python的版本號,若是版本大於3.6,就用第一個run函數,不然就用第二個run函數,這兩個函數有什麼不一樣——第一個run函數多了下面兩行session
encoding: Optional[str] = ..., errors: Optional[str] = ...)
但是,既然版本大於3.6和小於3.6都會調用已存在的run函數,那爲何會報錯?咱們來看一下比較完整的代碼函數
不知道有沒有留意到當版本大於3.5時,纔會去第二個if裏判斷是否大於3.6,而我當前的版本是3.4.4,所以不知足大於3.5的if判斷,而知足大於3.3的if判斷,此時下面的方法都是call了(事實上,只要知足版本<3.5,都應該調用的是call方法)ui
if sys.version_info >= (3, 5): class CompletedProcess: # morally: _CMD args = ... # type: Any returncode = ... # type: int # morally: Optional[_TXT] stdout = ... # type: Any stderr = ... # type: Any def __init__(self, args: _CMD, returncode: int, stdout: Optional[_TXT] = ..., stderr: Optional[_TXT] = ...) -> None: ... def check_returncode(self) -> None: ... if sys.version_info >= (3, 6): # Nearly same args as Popen.__init__ except for timeout, input, and check def run(args: _CMD, timeout: Optional[float] = ..., input: Optional[_TXT] = ..., check: bool = ..., bufsize: int = ..., executable: _PATH = ..., stdin: _FILE = ..., stdout: _FILE = ..., stderr: _FILE = ..., preexec_fn: Callable[[], Any] = ..., close_fds: bool = ..., shell: bool = ..., cwd: Optional[_PATH] = ..., env: Optional[_ENV] = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Any = ..., *, encoding: Optional[str] = ..., errors: Optional[str] = ...) -> CompletedProcess: ... else: # Nearly same args as Popen.__init__ except for timeout, input, and check def run(args: _CMD, timeout: Optional[float] = ..., input: Optional[_TXT] = ..., check: bool = ..., bufsize: int = ..., executable: _PATH = ..., stdin: _FILE = ..., stdout: _FILE = ..., stderr: _FILE = ..., preexec_fn: Callable[[], Any] = ..., close_fds: bool = ..., shell: bool = ..., cwd: Optional[_PATH] = ..., env: Optional[_ENV] = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Any = ...) -> CompletedProcess: ... # Same args as Popen.__init__ if sys.version_info >= (3, 3): # 3.3 added timeout def call(args: _CMD, bufsize: int = ..., executable: _PATH = ..., stdin: _FILE = ..., stdout: _FILE = ..., stderr: _FILE = ..., preexec_fn: Callable[[], Any] = ..., close_fds: bool = ..., shell: bool = ..., cwd: Optional[_PATH] = ..., env: Optional[_ENV] = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Any = ..., timeout: float = ...) -> int: ... else: def call(args: _CMD, bufsize: int = ..., executable: _PATH = ..., stdin: _FILE = ..., stdout: _FILE = ..., stderr: _FILE = ..., preexec_fn: Callable[[], Any] = ..., close_fds: bool = ..., shell: bool = ..., cwd: Optional[_PATH] = ..., env: Optional[_ENV] = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Any = ...) -> int: ...
瞭解這個,就知道如何解決了,只要修改源碼把run換成call便可(若是要使用3.5及以上的版本,建議把call再換回run)spa
再次使用pipenv shell,發現能夠切換到虛擬環境了rest