2015-07-20 66 views
1

我試圖用HTTPoison編寫一個網頁抓取工具。作爲第一步,我沿着下面的步驟寫了一個簡短的HTTP訪問代碼;Elixir:如何正確描述mix.exs設置?

  1. 通過混合

    創建一個項目$混用新httptest1

  2. 撰寫的lib/httptest1.ex短代碼。

    defmodule Httptest1 do 
        require HTTPoison 
    
        def test1 do 
        ret = HTTPoison.get! "http://www.yahoo.com" 
        %HTTPoison.Response{status_code: 200, body: body} = ret 
        IO.inspect body 
        end 
    end 
    
    Httptest1.test1() 
    
  3. 修改mix.exs爲HTTPoison。

    defmodule Httptest1.Mixfile do 
        use Mix.Project 
    
        def project do 
        [app: :httptest1, 
        version: "0.0.1", 
        elixir: "~> 1.0", 
        build_embedded: Mix.env == :prod, 
        start_permanent: Mix.env == :prod, 
        deps: deps] 
        end 
    
        # Configuration for the OTP application 
        def application do 
        [applications: [:logger, :httpoison]] 
        end 
    
        # Dependencies can be Hex packages: 
        # 
        defp deps do 
        [ 
        {:httpoison, "~> 0.6"} 
        ] 
        end 
    end 
    
  4. 運行$ mix deps.get的依賴關係。

  5. 運行$ mix run,則編譯失敗;

    ==> idna (compile) 
    Compiled src/idna.erl 
    Compiled src/idna_ucs.erl 
    Compiled src/punycode.erl 
    (... snip ...) 
    Generated httpoison app 
    
    == Compilation error on file lib/httptest1.ex == 
    ** (exit) exited in: :gen_server.call(:hackney_manager, {:new_request, #PID<0.154.0>, #Reference<0.0.1.1724>, {:client, :undefined, :hackney_dummy_metrics, :hackney_tcp_transport, 'www.yahoo.com', 80, "www.yahoo.com", [connect_timeout: 5000, recv_timeout: :infinity], nil, nil, nil, true, :hackney_pool, :infinity, false, 5, false, 5, nil, nil, nil, :undefined, :start, nil, :normal, false, false, false, false, nil, :waiting, nil, 4096, "", [], :undefined, nil, nil, nil, nil, :undefined, nil}}, :infinity) 
        ** (EXIT) no process 
        (stdlib) gen_server.erl:212: :gen_server.call/3 
        src/hackney_client/hackney_manager.erl:66: :hackney_manager.init_request/1 
        src/hackney_client/hackney_manager.erl:56: :hackney_manager.new_request/1 
        src/hackney_connect/hackney_connect.erl:181: :hackney_connect.socket_from_pool/4 
        src/hackney_connect/hackney_connect.erl:36: :hackney_connect.connect/5 
        src/hackney_client/hackney.erl:319: :hackney.request/5 
        lib/httpoison.ex:60: HTTPoison.request/5 
        lib/httpoison.ex:60: HTTPoison.request!/5 
    

當我使用$ iex -S mix代替,其結果是一樣的。

但是,如果我將httptest1.ex移動到放置mix.exs的相同目錄中,如$ mv lib/httptest1.ex .,並試圖明確指定源文件;它工作正常。

問題: 我懷疑我的mix.exs設置出了問題,那是什麼?

+0

我有類似的錯誤信息。該代碼在IEX中正確執行且沒有錯誤,但在運行混合任務時會引發錯誤。爲我工作的解決方案是「HTTPoison.start」也許這有助於在另一種情況下出現類似錯誤消息的人。 –

回答

2

全部.exlib/被編譯。由於Elixir是編譯文件時的元編程語言,因此您實際上正在運行代碼。這意味着編譯項目時會執行Httptest1.test1()

HTTPoison需要啓動才能正常工作。它是在您的應用程序啓動時啓動的,當您執行mix run ...時。但是當你的項目正在編譯你的項目,或者你的依賴沒有啓動,因此對你的依賴關係的調用可能會失敗。

查看本章Supervisor and Application的入門指南,瞭解如何在應用程序啓動時運行代碼。

+0

謝謝。至少我發現只需從我的代碼中省略Httptest1.test1(),然後手動啓動$ iex -S mix和Httptest1.test1即可。我的另一個問題是,爲什麼指定的.ex文件直接在沒有放在./lib時工作。 – HirofumiTamori

+0

因爲它不會與您的項目一起編譯。它運行(並編譯),當你做'混合運行...',這將使你的HTTPoison已經啓動並運行。 –

+0

換句話說,'$ mix run httptest1.ex'編譯lib和依賴模塊下的文件,但只在HTTPoison啓動後運行./httptest1.ex,它是正確的嗎? – HirofumiTamori

0

改進!現在我知道如何創建一個可執行的調用命令行。

程序;

defmodule Httptest1 do 
    use Application 
    require HTTPoison 

    def start(_type, _args) do 
    import Supervisor.Spec, warn: false 
    children = [] 
    opts = [strategy: :one_for_one, name: Httptest1.Supervisor] 
    Supervisor.start_link(children, opts) 
    end 

    def main(args) do # entry point 
    ret = HTTPoison.get! "http://www.yahoo.com" 
    %HTTPoison.Response{status_code: _, body: body} = ret # no status code matching now 
    IO.inspect body 
    end 

end 

和mix.exs(均由$ mix new httptest1 --sup supervisor選項創建);

Httptest.test1 $ iex -S mix類型調用IEX
defmodule Httptest1.Mixfile do 
    use Mix.Project 

    def project do 
    [app: :httptest1, 
    version: "0.0.1", 
    elixir: "~> 1.0", 
    build_embedded: Mix.env == :prod, 
    start_permanent: Mix.env == :prod, 
    escript: escript, # <<<< Added 
    deps: deps] 
    end 

    def escript do # define escript 
    [main_module: Httptest1] 
    end 

    def application do 
    [applications: [:logger, :httpoison], 
    mod: {Httptest1, []}] # 
    end 

    defp deps do 
    [ 
     {:httpoison, "~> 0.6"} 
    ] 
    end 
end 

然後,預期的結果登場!謝謝。

此外,爲了創建命令行可執行,

$ mix escript.build 

則產生./httptest1。完成。