標籤:ted 沒有 let 用法 lse session style 虛擬環境 targe
利用pipenv shell切換到虛擬環境時,顯示報錯:AttributeError: ‘module‘ object has no attribute ‘run‘
可以看到是d:\program\python34\lib\site-packages\pipenv\shells.py檔案的第62行報錯了,提示模組沒有run的屬性,於是就跑到該檔案的第62行去看
選中run,CTRL+B發現能看到源碼,源碼如下:
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函數多了下面兩行
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方法)
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)
再次使用pipenv shell,發現可以切換到虛擬環境了
參考文章
https://cuiqingcai.com/5846.html
解決:pipenv shell報錯:AttributeError: 'module' object has no attribute 'run'